Skip to content

Commit f5576c3

Browse files
committed
ri now walks the ancestors looking for a method definition
1 parent 41e38e5 commit f5576c3

File tree

10 files changed

+201
-116
lines changed

10 files changed

+201
-116
lines changed

History.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* N Major Enhancements:
44
* RDoc now knows about meta-programmed methods, see RDoc::Parser::Ruby
55
* Reorganized parsers under RDoc::Parser base class
6+
* ri now walks the ancestors of a class looking for a method
67
* N Minor Enhancements:
78
* Allow links to files
89
* Default options now taken from RDOCOPT environment variable

lib/rdoc/code_objects.rb

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,15 @@ def find_module_named(name)
609609
find_class_or_module_named(name) || find_enclosing_module_named(name)
610610
end
611611

612+
def inspect
613+
"#<%s:0x%x %p modules: %p classes: %p>" % [
614+
self.class, object_id,
615+
file_base_name,
616+
@modules.map { |n,m| m },
617+
@classes.map { |n,c| c }
618+
]
619+
end
620+
612621
end
613622

614623
##
@@ -617,7 +626,6 @@ def find_module_named(name)
617626

618627
class ClassModule < Context
619628

620-
attr_reader :superclass
621629
attr_accessor :diagram
622630

623631
def initialize(name, superclass = nil)
@@ -628,7 +636,15 @@ def initialize(name, superclass = nil)
628636
super()
629637
end
630638

639+
def find_class_named(name)
640+
return self if full_name == name
641+
@classes.each_value {|c| return c if c.find_class_named(name) }
642+
nil
643+
end
644+
645+
##
631646
# Return the fully qualified name of this class or module
647+
632648
def full_name
633649
if @parent && @parent.full_name
634650
@parent.full_name + "::" + @name
@@ -642,24 +658,35 @@ def http_url(prefix)
642658
File.join(prefix, *path) + ".html"
643659
end
644660

645-
# Return +true+ if this object represents a module
646-
def is_module?
661+
##
662+
# Does this object represent a module?
663+
664+
def module?
647665
false
648666
end
649667

650-
# to_s is simply for debugging
651-
def to_s
652-
res = self.class.name + ": " + @name
653-
res << @comment.to_s
654-
res << super
655-
res
668+
##
669+
# The superclass of this class
670+
671+
def superclass
672+
raise NoMethodError, "#{full_name} is a module" if module?
673+
674+
scope = self
675+
676+
until TopLevel === scope do
677+
superclass = scope.classes.find { |c| c.name == @superclass }
678+
679+
return superclass.full_name if superclass
680+
scope = scope.parent
681+
end
682+
683+
@superclass
656684
end
657685

658-
def find_class_named(name)
659-
return self if full_name == name
660-
@classes.each_value {|c| return c if c.find_class_named(name) }
661-
nil
686+
def to_s
687+
"#{self.class}: #{@name} #{@comment} #{super}"
662688
end
689+
663690
end
664691

665692
##
@@ -708,7 +735,7 @@ def inspect
708735
]
709736
end
710737

711-
def is_module?
738+
def module?
712739
true
713740
end
714741

lib/rdoc/generator.rb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,7 @@ def initialize(context, html_file, prefix, options)
489489

490490
@html_file = html_file
491491
@html_class = self
492-
@is_module = context.is_module?
492+
@is_module = context.module?
493493
@values = {}
494494

495495
context.viewer = self
@@ -619,16 +619,16 @@ def class_attribute_values
619619
@values["title"] = "#{@values['classmod']}: #{h_name}"
620620

621621
c = @context
622-
c = c.parent while c and !c.diagram
623-
if c && c.diagram
622+
c = c.parent while c and not c.diagram
623+
624+
if c and c.diagram then
624625
@values["diagram"] = diagram_reference(c.diagram)
625626
end
626627

627628
@values["full_name"] = h_name
628629

629-
parent_class = @context.superclass
630-
631-
if parent_class
630+
if not @context.module? and @context.superclass then
631+
parent_class = @context.superclass
632632
@values["parent"] = CGI.escapeHTML(parent_class)
633633

634634
if parent_name

lib/rdoc/generator/ri.rb

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,8 @@ def self.for(options)
1616
new(options)
1717
end
1818

19-
class << self
20-
protected :new
21-
end
22-
2319
##
24-
# Set up a new RDoc::Generator::RI.
20+
# Set up a new ri generator
2521

2622
def initialize(options) #:not-new:
2723
@options = options
@@ -52,11 +48,12 @@ def process_class(from_class)
5248
end
5349

5450
def generate_class_info(cls)
55-
if cls === RDoc::NormalModule
51+
case cls
52+
when RDoc::NormalModule then
5653
cls_desc = RDoc::RI::ModuleDescription.new
5754
else
5855
cls_desc = RDoc::RI::ClassDescription.new
59-
cls_desc.superclass = cls.superclass
56+
cls_desc.superclass = cls.superclass
6057
end
6158

6259
cls_desc.name = cls.name

lib/rdoc/parser/ruby.rb

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1872,7 +1872,7 @@ def parse_call_parameters(tk)
18721872
res
18731873
end
18741874

1875-
def parse_class(container, single, tk, comment, &block)
1875+
def parse_class(container, single, tk, comment)
18761876
progress("c")
18771877

18781878
@stats.num_classes += 1
@@ -1891,22 +1891,19 @@ def parse_class(container, single, tk, comment, &block)
18911891
superclass = "<unknown>" if superclass.empty?
18921892
end
18931893

1894-
if single == SINGLE
1895-
cls_type = RDoc::SingleClass
1896-
else
1897-
cls_type = RDoc::NormalClass
1898-
end
1899-
1894+
cls_type = single == SINGLE ? RDoc::SingleClass : RDoc::NormalClass
19001895
cls = container.add_class cls_type, name, superclass
1896+
19011897
read_documentation_modifiers cls, RDoc::CLASS_MODIFIERS
1902-
cls.record_location(@top_level)
1903-
parse_statements(cls)
1898+
cls.record_location @top_level
1899+
1900+
parse_statements cls
19041901
cls.comment = comment
19051902

19061903
when TkLSHFT
19071904
case name = get_class_specification
19081905
when "self", container.name
1909-
parse_statements(container, SINGLE, &block)
1906+
parse_statements(container, SINGLE)
19101907
else
19111908
other = RDoc::TopLevel.find_class_named(name)
19121909
unless other
@@ -1916,7 +1913,7 @@ def parse_class(container, single, tk, comment, &block)
19161913
other = RDoc::NormalClass.new "Dummy", nil
19171914
end
19181915
read_documentation_modifiers other, RDoc::CLASS_MODIFIERS
1919-
parse_statements(other, SINGLE, &block)
1916+
parse_statements(other, SINGLE)
19201917
end
19211918

19221919
else
@@ -2293,7 +2290,7 @@ def parse_module(container, single, tk, comment)
22932290
progress("m")
22942291
@stats.num_modules += 1
22952292
container, name_t = get_class_or_module(container)
2296-
# skip_tkspace
2293+
22972294
name = name_t.name
22982295

22992296
mod = container.add_module RDoc::NormalModule, name

lib/rdoc/ri/driver.rb

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -335,13 +335,13 @@ def load_cache_for(klassname)
335335

336336
if File.exist? path and
337337
File.mtime(path) >= File.mtime(class_cache_file_path) then
338-
File.open path, 'rb' do |fp|
338+
open path, 'rb' do |fp|
339339
cache = Marshal.load fp.read
340340
end
341341
else
342342
class_cache = nil
343343

344-
File.open class_cache_file_path, 'rb' do |fp|
344+
open class_cache_file_path, 'rb' do |fp|
345345
class_cache = Marshal.load fp.read
346346
end
347347

@@ -372,17 +372,34 @@ def load_cache_for(klassname)
372372
RDoc::RI::Driver::Hash.convert cache
373373
end
374374

375+
##
376+
# Finds the next ancestor of +orig_klass+ after +klass+.
377+
378+
def lookup_ancestor(klass, orig_klass, ancestor = nil)
379+
cache = class_cache[orig_klass]
380+
381+
return nil unless cache
382+
383+
ancestors ||= [orig_klass]
384+
ancestors.push(*cache.includes.map { |inc| inc['name'] })
385+
ancestors << cache.superclass
386+
387+
ancestor = ancestors[ancestors.index(klass) + 1]
388+
389+
return ancestor if ancestor
390+
391+
lookup_ancestor klass, cache.superclass
392+
end
393+
375394
##
376395
# Finds the method
377396

378397
def lookup_method(name, klass)
379398
cache = load_cache_for klass
380-
raise NotFoundError, name unless cache
399+
return nil unless cache
381400

382401
method = cache[name.gsub('.', '#')]
383402
method = cache[name.gsub('.', '::')] unless method
384-
raise NotFoundError, name unless method
385-
386403
method
387404
end
388405

@@ -459,11 +476,25 @@ def run
459476
if class_cache.key? name then
460477
display_class name
461478
else
462-
meth = nil
479+
klass, = parse_name name
480+
481+
orig_klass = klass
482+
orig_name = name
483+
484+
until klass == 'Kernel' do
485+
method = lookup_method name, klass
486+
487+
break method if method
463488

464-
klass, meth = parse_name name
489+
ancestor = lookup_ancestor klass, orig_klass
465490

466-
method = lookup_method name, klass
491+
break unless ancestor
492+
493+
name = name.sub klass, ancestor
494+
klass = ancestor
495+
end
496+
497+
raise NotFoundError, orig_name unless method
467498

468499
@display.display_method_info method
469500
end
@@ -472,6 +503,7 @@ def run
472503
display_class name
473504
else
474505
methods = select_methods(/^#{name}/)
506+
475507
if methods.size == 0
476508
raise NotFoundError, name
477509
elsif methods.size == 1

test/test_rdoc_info_formatting.rb

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,25 @@
1-
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib/'
21
require 'fileutils'
2+
require 'tmpdir'
33
require 'test/unit'
4+
45
require 'rdoc/generator/texinfo'
5-
require 'yaml'
66

77
# From chapter 18 of the Pickaxe 3rd ed. and the TexInfo manual.
88
class TestRdocInfoFormatting < Test::Unit::TestCase
9-
OUTPUT_DIR = "/tmp/rdoc-#{$$}"
10-
119
def setup
12-
# supress stdout
13-
$stdout = File.new('/dev/null','w')
14-
$stderr = File.new('/dev/null','w')
10+
@output_dir = File.join Dir.tmpdir, "test_rdoc_info_formatting_#{$$}"
11+
@output_file = File.join @output_dir, 'rdoc.texinfo'
1512

16-
RDoc::RDoc.new.document(['--fmt=texinfo',
13+
RDoc::RDoc.new.document(['--fmt=texinfo', '--quiet',
1714
File.expand_path(__FILE__),
18-
"--op=#{OUTPUT_DIR}"])
19-
@text = File.read(OUTPUT_DIR + '/rdoc.texinfo')
15+
"--op=#{@output_dir}"])
16+
@text = File.read @output_file
17+
2018
# File.open('rdoc.texinfo', 'w') { |f| f.puts @text }
2119
end
2220

2321
def teardown
24-
$stdout = STDOUT
25-
$stderr = STDERR
26-
FileUtils.rm_rf OUTPUT_DIR
22+
FileUtils.rm_rf @output_dir
2723
end
2824

2925
# Make sure tags like *this* do not make HTML

test/test_rdoc_info_sections.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ def test_methods_are_shown_only_once
7676

7777
# if system "makeinfo --version > /dev/null"
7878
# def test_compiles_to_info
79-
# makeinfo_output = `cd #{OUTPUT_DIR} && makeinfo rdoc.texinfo`
80-
# assert(File.exist?(File.join(OUTPUT_DIR, 'rdoc.info')),
79+
# makeinfo_output = `cd #{@output_dir} && makeinfo rdoc.texinfo`
80+
# assert(File.exist?(File.join(@output_dir, 'rdoc.info')),
8181
# "Info file was not compiled: #{makeinfo_output}")
8282
# end
8383
# end

0 commit comments

Comments
 (0)