Skip to content

Commit 17c0d6f

Browse files
authored
Fix cross-reference resolution for constants (#1539)
This PR resolves #1011 by ensuring that constant names ~~with `::` (e.g. `::CONSTANT_NAME`) can be used to find constants in contexts~~ can be resolved by `RDoc::CrossReference#resolve_local_symbol` (originally named `resolve_method`). Please note that the darkfish and aliki themes do not display links for constants in the constants section (just the names of the constants in a description list), so the changes in this PR just make it possible to cross reference constants. I will create a separate PR to propose changes to the themes.
1 parent c3eea6e commit 17c0d6f

File tree

5 files changed

+42
-23
lines changed

5 files changed

+42
-23
lines changed

lib/rdoc/cross_reference.rb

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -132,47 +132,56 @@ def initialize(context)
132132
end
133133

134134
##
135-
# Returns a method reference to +name+.
135+
# Returns a method, attribute or constant reference to +name+
136+
# if it exists in the containing context object. It returns
137+
# nil otherwise.
138+
#
139+
# For example, this method would decompose name = 'A::CONSTANT' into a
140+
# container object A and a symbol 'CONSTANT', and it would try to find
141+
# 'CONSTANT' in A.
136142

137-
def resolve_method(name)
143+
def resolve_local_symbol(name)
138144
ref = nil
145+
type = nil
146+
container = nil
139147

140-
if /#{CLASS_REGEXP_STR}([.#]|::)#{METHOD_REGEXP_STR}/o =~ name then
148+
case name
149+
when /#{CLASS_REGEXP_STR}::([A-Z]\w*)\z/o then
150+
symbol = $2
151+
container = @context.find_symbol_module($1)
152+
when /#{CLASS_REGEXP_STR}([.#]|::)#{METHOD_REGEXP_STR}/o then
141153
type = $2
142154
if '.' == type # will find either #method or ::method
143-
method = $3
155+
symbol = $3
144156
else
145-
method = "#{type}#{$3}"
157+
symbol = "#{type}#{$3}"
146158
end
147159
container = @context.find_symbol_module($1)
148-
elsif /^([.#]|::)#{METHOD_REGEXP_STR}/o =~ name then
160+
when /^([.#]|::)#{METHOD_REGEXP_STR}/o then
149161
type = $1
150162
if '.' == type
151-
method = $2
163+
symbol = $2
152164
else
153-
method = "#{type}#{$2}"
165+
symbol = "#{type}#{$2}"
154166
end
155167
container = @context
156-
else
157-
type = nil
158-
container = nil
159168
end
160169

161170
if container then
162171
unless RDoc::TopLevel === container then
163172
if '.' == type then
164-
if 'new' == method then # AnyClassName.new will be class method
165-
ref = container.find_local_symbol method
166-
ref = container.find_ancestor_local_symbol method unless ref
173+
if 'new' == symbol then # AnyClassName.new will be class method
174+
ref = container.find_local_symbol symbol
175+
ref = container.find_ancestor_local_symbol symbol unless ref
167176
else
168-
ref = container.find_local_symbol "::#{method}"
169-
ref = container.find_ancestor_local_symbol "::#{method}" unless ref
170-
ref = container.find_local_symbol "##{method}" unless ref
171-
ref = container.find_ancestor_local_symbol "##{method}" unless ref
177+
ref = container.find_local_symbol "::#{symbol}"
178+
ref = container.find_ancestor_local_symbol "::#{symbol}" unless ref
179+
ref = container.find_local_symbol "##{symbol}" unless ref
180+
ref = container.find_ancestor_local_symbol "##{symbol}" unless ref
172181
end
173182
else
174-
ref = container.find_local_symbol method
175-
ref = container.find_ancestor_local_symbol method unless ref
183+
ref = container.find_local_symbol symbol
184+
ref = container.find_ancestor_local_symbol symbol unless ref
176185
end
177186
end
178187
end
@@ -197,7 +206,7 @@ def resolve(name, text)
197206
@context.find_symbol name
198207
end
199208

200-
ref = resolve_method name unless ref
209+
ref = resolve_local_symbol name unless ref
201210

202211
# Try a page name
203212
ref = @store.page name if not ref and name =~ /^[\w.\/]+$/

test/rdoc/rdoc_cross_reference_test.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,12 @@ def test_resolve_method
157157
assert_ref @c2_c3_m, '::C2::C3#m(*)'
158158
end
159159

160+
def test_resolve_constant
161+
assert_ref @c1_const, 'CONST'
162+
assert_ref @c1_const, 'C1::CONST'
163+
assert_ref @c1_const, 'C12::CONST'
164+
end
165+
160166
def test_resolve_the_same_name_in_instance_and_class_method
161167
assert_ref @c9_a_i_foo, 'C9::A#foo'
162168
assert_ref @c9_a_c_bar, 'C9::A::bar'

test/rdoc/rdoc_store_test.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ def test_add_file_relative
163163

164164
def test_all_classes_and_modules
165165
expected = %w[
166-
C1 C10 C10::C11 C11 C2 C2::C3 C2::C3::H1 C3 C3::H1 C3::H2 C4 C4::C4 C5 C5::C1 C6 C7 C8 C9 C9::A C9::B
166+
C1 C10 C10::C11 C11 C12 C2 C2::C3 C2::C3::H1 C3 C3::H1 C3::H2 C4 C4::C4 C5 C5::C1 C6 C7 C8 C9 C9::A C9::B
167167
Child
168168
M1 M1::M2
169169
Object
@@ -219,7 +219,7 @@ def test_class_path
219219

220220
def test_classes
221221
expected = %w[
222-
C1 C10 C10::C11 C11 C2 C2::C3 C2::C3::H1 C3 C3::H1 C3::H2 C4 C4::C4 C5 C5::C1 C6 C7 C8 C9 C9::A C9::B
222+
C1 C10 C10::C11 C11 C12 C2 C2::C3 C2::C3::H1 C3 C3::H1 C3::H2 C4 C4::C4 C5 C5::C1 C6 C7 C8 C9 C9::A C9::B
223223
Child
224224
Object
225225
Parent

test/rdoc/xref_data.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,9 @@ class C11
145145
def C11
146146
end
147147
148+
class C12 < C1
149+
end
150+
148151
module M1
149152
def m
150153
end

test/rdoc/xref_test_case.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ def setup
3333
@c1__m = @c1.find_class_method_named 'm' # C1::m
3434
@c1_m = @c1.find_instance_method_named 'm' # C1#m
3535
@c1_plus = @c1.find_instance_method_named '+'
36+
@c1_const = @c1.find_constant_named 'CONST'
3637

3738
@c2 = @xref_data.find_module_named 'C2'
3839
@c2_a = @c2.method_list.last

0 commit comments

Comments
 (0)