From cd9e9c6debcf893ea5fa70e42dc1875afaf0066f Mon Sep 17 00:00:00 2001 From: drbrain Date: Mon, 21 Jul 2008 18:35:14 +0000 Subject: Update to RDoc 2.1.0 r112 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@18147 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 4 + lib/rdoc/code_objects.rb | 131 +++++++++++++++++++++---------- lib/rdoc/generator.rb | 12 +-- lib/rdoc/generator/ri.rb | 11 +-- lib/rdoc/markup/attribute_manager.rb | 7 -- lib/rdoc/options.rb | 31 ++++++-- lib/rdoc/parser.rb | 3 - lib/rdoc/parser/c.rb | 32 +++----- lib/rdoc/parser/f95.rb | 58 +++++++------- lib/rdoc/parser/ruby.rb | 72 ++++++----------- lib/rdoc/rdoc.rb | 38 +++++---- lib/rdoc/ri/descriptions.rb | 8 +- lib/rdoc/ri/driver.rb | 53 +++++++++++-- lib/rdoc/stats.rb | 98 ++++++++++++++++++++++- test/rdoc/test_rdoc_info_formatting.rb | 22 +++--- test/rdoc/test_rdoc_info_sections.rb | 4 +- test/rdoc/test_rdoc_parser_c.rb | 10 +-- test/rdoc/test_rdoc_parser_ruby.rb | 139 +++++++++++++++++++++------------ test/rdoc/test_rdoc_ri_driver.rb | 12 +-- 19 files changed, 460 insertions(+), 285 deletions(-) diff --git a/ChangeLog b/ChangeLog index c5be9facf6..a9f8af46b2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +Tue Jul 22 03:34:01 2008 Eric Hodel + + * lib/rdoc*: Update to RDoc 2.1.0 r112. + Tue Jul 22 02:51:46 2008 Nobuyoshi Nakada * include/ruby/intern.h (rb_str_buf_cat2, rb_str_cat2): optimization diff --git a/lib/rdoc/code_objects.rb b/lib/rdoc/code_objects.rb index 58adc5a351..fbdb612b92 100644 --- a/lib/rdoc/code_objects.rb +++ b/lib/rdoc/code_objects.rb @@ -71,6 +71,14 @@ module RDoc # Do we _force_ documentation, even is we wouldn't normally show the entity attr_accessor :force_documentation + def parent_file_name + @parent ? @parent.file_base_name : '(unknown)' + end + + def parent_name + @parent ? @parent.name : '(unknown)' + end + # Default callbacks to nothing, but this is overridden for classes # and modules def remove_classes_and_modules @@ -264,7 +272,7 @@ module RDoc end def add_class(class_type, name, superclass) - add_class_or_module(@classes, class_type, name, superclass) + add_class_or_module @classes, class_type, name, superclass end def add_module(class_type, name) @@ -272,7 +280,6 @@ module RDoc end def add_method(a_method) - puts "Adding #@visibility method #{a_method.name} to #@name" if $DEBUG_RDOC a_method.visibility = @visibility add_to(@method_list, a_method) end @@ -283,7 +290,8 @@ module RDoc def add_alias(an_alias) meth = find_instance_method_named(an_alias.old_name) - if meth + + if meth then new_meth = AnyMethod.new(an_alias.text, an_alias.new_name) new_meth.is_alias_for = meth new_meth.singleton = meth.singleton @@ -294,6 +302,8 @@ module RDoc else add_to(@aliases, an_alias) end + + an_alias end def add_include(an_include) @@ -315,11 +325,12 @@ module RDoc def add_class_or_module(collection, class_type, name, superclass=nil) cls = collection[name] - if cls + + if cls then + cls.superclass = superclass unless cls.module? puts "Reusing class/module #{name}" if $DEBUG_RDOC else cls = class_type.new(name, superclass) - puts "Adding class/module #{name} to #@name" if $DEBUG_RDOC # collection[name] = cls if @document_self && !@done_documenting collection[name] = cls if !@done_documenting cls.parent = self @@ -550,10 +561,11 @@ module RDoc def add_class_or_module(collection, class_type, name, superclass) cls = collection[name] - if cls - puts "Reusing class/module #{name}" #if $DEBUG_RDOC + if cls then + cls.superclass = superclass unless cls.module? + puts "Reusing class/module #{cls.full_name}" if $DEBUG_RDOC else - if class_type == NormalModule + if class_type == NormalModule then all = @@all_modules else all = @@all_classes @@ -561,13 +573,11 @@ module RDoc cls = all[name] - if !cls - cls = class_type.new(name, superclass) + unless cls then + cls = class_type.new name, superclass all[name] = cls unless @done_documenting end - puts "Adding class/module #{name} to #{@name}" if $DEBUG_RDOC - collection[name] = cls unless @done_documenting cls.parent = self @@ -609,6 +619,15 @@ module RDoc find_class_or_module_named(name) || find_enclosing_module_named(name) end + def inspect + "#<%s:0x%x %p modules: %p classes: %p>" % [ + self.class, object_id, + file_base_name, + @modules.map { |n,m| m }, + @classes.map { |n,c| c } + ] + end + end ## @@ -617,7 +636,6 @@ module RDoc class ClassModule < Context - attr_reader :superclass attr_accessor :diagram def initialize(name, superclass = nil) @@ -628,7 +646,15 @@ module RDoc super() end + def find_class_named(name) + return self if full_name == name + @classes.each_value {|c| return c if c.find_class_named(name) } + nil + end + + ## # Return the fully qualified name of this class or module + def full_name if @parent && @parent.full_name @parent.full_name + "::" + @name @@ -642,24 +668,47 @@ module RDoc File.join(prefix, *path) + ".html" end - # Return +true+ if this object represents a module - def is_module? + ## + # Does this object represent a module? + + def module? false end - # to_s is simply for debugging - def to_s - res = self.class.name + ": " + @name - res << @comment.to_s - res << super - res + ## + # Get the superclass of this class. Attempts to retrieve the superclass' + # real name by following module nesting. + + def superclass + raise NoMethodError, "#{full_name} is a module" if module? + + scope = self + + begin + superclass = scope.classes.find { |c| c.name == @superclass } + + return superclass.full_name if superclass + scope = scope.parent + end until scope.nil? or TopLevel === scope + + @superclass end - def find_class_named(name) - return self if full_name == name - @classes.each_value {|c| return c if c.find_class_named(name) } - nil + ## + # Set the superclass of this class + + def superclass=(superclass) + raise NoMethodError, "#{full_name} is a module" if module? + + if @superclass.nil? or @superclass == 'Object' then + @superclass = superclass + end end + + def to_s + "#{self.class}: #{@name} #{@comment} #{super}" + end + end ## @@ -708,7 +757,7 @@ module RDoc ] end - def is_module? + def module? true end @@ -764,7 +813,7 @@ module RDoc alias_for = @is_alias_for ? " (alias for #{@is_alias_for.name})" : nil "#<%s:0x%x %s%s%s (%s)%s>" % [ self.class, object_id, - @parent.name, + parent_name, singleton ? '::' : '#', name, visibility, @@ -773,25 +822,24 @@ module RDoc end def param_seq - p = params.gsub(/\s*\#.*/, '') - p = p.tr("\n", " ").squeeze(" ") - p = "(" + p + ")" unless p[0] == ?( + params = params.gsub(/\s*\#.*/, '') + params = params.tr("\n", " ").squeeze(" ") + params = "(#{params})" unless p[0] == ?( - if (block = block_params) - # If this method has explicit block parameters, remove any - # explicit &block -$stderr.puts p - p.sub!(/,?\s*&\w+/) -$stderr.puts p + if block = block_params then # yes, = + # If this method has explicit block parameters, remove any explicit + # &block + params.sub!(/,?\s*&\w+/) block.gsub!(/\s*\#.*/, '') block = block.tr("\n", " ").squeeze(" ") if block[0] == ?( block.sub!(/^\(/, '').sub!(/\)/, '') end - p << " {|#{block}| ...}" + params << " { |#{block}| ... }" end - p + + params end def to_s @@ -887,7 +935,7 @@ $stderr.puts p "#<%s:0x%x %s.%s :%s>" % [ self.class, object_id, - @parent.name, attr, @name, + parent_name, attr, @name, ] end @@ -914,7 +962,7 @@ $stderr.puts p self.class, object_id, @name, - @parent.file_base_name, + parent_file_name, ] end @@ -938,8 +986,7 @@ $stderr.puts p "#<%s:0x%x %s.include %s>" % [ self.class, object_id, - @parent.name, - @name, + parent_name, @name, ] end diff --git a/lib/rdoc/generator.rb b/lib/rdoc/generator.rb index 00a5ad45db..fbc08c4e20 100644 --- a/lib/rdoc/generator.rb +++ b/lib/rdoc/generator.rb @@ -489,7 +489,7 @@ module RDoc::Generator @html_file = html_file @html_class = self - @is_module = context.is_module? + @is_module = context.module? @values = {} context.viewer = self @@ -619,16 +619,16 @@ module RDoc::Generator @values["title"] = "#{@values['classmod']}: #{h_name}" c = @context - c = c.parent while c and !c.diagram - if c && c.diagram + c = c.parent while c and not c.diagram + + if c and c.diagram then @values["diagram"] = diagram_reference(c.diagram) end @values["full_name"] = h_name - parent_class = @context.superclass - - if parent_class + if not @context.module? and @context.superclass then + parent_class = @context.superclass @values["parent"] = CGI.escapeHTML(parent_class) if parent_name diff --git a/lib/rdoc/generator/ri.rb b/lib/rdoc/generator/ri.rb index d347505e0b..6b7a5932f8 100644 --- a/lib/rdoc/generator/ri.rb +++ b/lib/rdoc/generator/ri.rb @@ -16,12 +16,8 @@ class RDoc::Generator::RI new(options) end - class << self - protected :new - end - ## - # Set up a new RDoc::Generator::RI. + # Set up a new ri generator def initialize(options) #:not-new: @options = options @@ -52,11 +48,12 @@ class RDoc::Generator::RI end def generate_class_info(cls) - if cls === RDoc::NormalModule + case cls + when RDoc::NormalModule then cls_desc = RDoc::RI::ModuleDescription.new else cls_desc = RDoc::RI::ClassDescription.new - cls_desc.superclass = cls.superclass + cls_desc.superclass = cls.superclass end cls_desc.name = cls.name diff --git a/lib/rdoc/markup/attribute_manager.rb b/lib/rdoc/markup/attribute_manager.rb index ae8b77f22e..d13b79376c 100644 --- a/lib/rdoc/markup/attribute_manager.rb +++ b/lib/rdoc/markup/attribute_manager.rb @@ -174,21 +174,16 @@ class RDoc::Markup::AttributeManager def flow(str) @str = str - puts("Before flow, str='#{@str.dump}'") if $DEBUG_RDOC mask_protected_sequences @attrs = RDoc::Markup::AttrSpan.new @str.length - puts("After protecting, str='#{@str.dump}'") if $DEBUG_RDOC - convert_attrs(@str, @attrs) convert_html(@str, @attrs) convert_specials(str, @attrs) unmask_protected_sequences - puts("After flow, str='#{@str.dump}'") if $DEBUG_RDOC - return split_into_flow end @@ -215,8 +210,6 @@ class RDoc::Markup::AttributeManager end def split_into_flow - display_attributes if $DEBUG_RDOC - res = [] current_attr = 0 str = "" diff --git a/lib/rdoc/options.rb b/lib/rdoc/options.rb index 886d9f77cd..d683a14022 100644 --- a/lib/rdoc/options.rb +++ b/lib/rdoc/options.rb @@ -107,11 +107,6 @@ class RDoc::Options attr_reader :promiscuous - ## - # Don't display progress as we process the files - - attr_accessor :quiet - ## # Array of directories to search for files to satisfy an :include: @@ -149,6 +144,11 @@ class RDoc::Options attr_reader :title + ## + # Verbosity, zero means quiet + + attr_accessor :verbosity + ## # URL of web cvs frontend @@ -161,7 +161,6 @@ class RDoc::Options @main_page = nil @merge = false @exclude = [] - @quiet = false @generators = generators @generator_name = 'html' @generator = @generators[@generator_name] @@ -180,6 +179,7 @@ class RDoc::Options @extra_accessor_flags = {} @promiscuous = false @force_update = false + @verbosity = 1 @css = nil @webcvs = nil @@ -424,9 +424,15 @@ Usage: #{opt.program_name} [options] [names...] opt.on("--quiet", "-q", "Don't show progress as we parse.") do |value| - @quiet = value + @verbosity = 0 + end + + opt.on("--verbose", "-v", + "Display extra progress as we parse.") do |value| + @verbosity = 2 end + opt.separator nil opt.on("--ri", "-r", @@ -559,6 +565,17 @@ Usage: #{opt.program_name} [options] [names...] @title ||= string end + ## + # Don't display progress as we process the files + + def quiet + @verbosity.zero? + end + + def quiet=(bool) + @verbosity = bool ? 0 : 1 + end + private ## diff --git a/lib/rdoc/parser.rb b/lib/rdoc/parser.rb index 4472a8bb7c..794fad00e9 100644 --- a/lib/rdoc/parser.rb +++ b/lib/rdoc/parser.rb @@ -46,8 +46,6 @@ class RDoc::Parser attr_reader :parsers end - attr_writer :progress - ## # Alias an extension to another extension. After this call, files ending # "new_ext" will be parsed using the same parser as "old_ext" @@ -103,7 +101,6 @@ class RDoc::Parser @content = content @options = options @stats = stats - @progress = $stderr unless options.quiet end end diff --git a/lib/rdoc/parser/c.rb b/lib/rdoc/parser/c.rb index 1db1e442c7..43bb767da9 100644 --- a/lib/rdoc/parser/c.rb +++ b/lib/rdoc/parser/c.rb @@ -95,8 +95,6 @@ class RDoc::Parser::C < RDoc::Parser parse_files_matching(/\.(?:([CcHh])\1?|c([+xp])\2|y)\z/) - attr_writer :progress - @@enclosure_classes = {} @@known_bodies = {} @@ -115,11 +113,12 @@ class RDoc::Parser::C < RDoc::Parser def do_aliases @content.scan(%r{rb_define_alias\s*\(\s*(\w+),\s*"([^"]+)",\s*"([^"]+)"\s*\)}m) do |var_name, new_name, old_name| - @stats.num_methods += 1 class_name = @known_classes[var_name] || var_name class_obj = find_class(var_name, class_name) - class_obj.add_alias RDoc::Alias.new("", old_name, new_name, "") + as = class_obj.add_alias RDoc::Alias.new("", old_name, new_name, "") + + @stats.add_alias as end end @@ -306,7 +305,7 @@ class RDoc::Parser::C < RDoc::Parser meth_obj.comment = mangle_comment(comment) + meth_obj.comment when %r{^\s*\#\s*define\s+#{meth_name}\s+(\w+)}m unless find_body($1, meth_obj, body, true) - warn "No definition for #{meth_name}" unless quiet + warn "No definition for #{meth_name}" unless @options.quiet return false end else @@ -318,7 +317,7 @@ class RDoc::Parser::C < RDoc::Parser find_modifiers(comment, meth_obj) meth_obj.comment = mangle_comment(comment) else - warn "No definition for #{meth_name}" unless quiet + warn "No definition for #{meth_name}" unless @options.quiet return false end end @@ -460,8 +459,6 @@ class RDoc::Parser::C < RDoc::Parser end def handle_class_module(var_name, class_mod, class_name, parent, in_module) - progress(class_mod[0, 1]) - parent_name = @known_classes[parent] || parent if in_module @@ -482,13 +479,14 @@ class RDoc::Parser::C < RDoc::Parser enclosure = @top_level end - if class_mod == "class" + if class_mod == "class" then cm = enclosure.add_class RDoc::NormalClass, class_name, parent_name - @stats.num_classes += 1 + @stats.add_class cm else cm = enclosure.add_module RDoc::NormalModule, class_name - @stats.num_modules += 1 + @stats.add_module cm end + cm.record_location(enclosure.toplevel) find_class_comment(cm.full_name, cm) @@ -560,9 +558,6 @@ class RDoc::Parser::C < RDoc::Parser def handle_method(type, var_name, meth_name, meth_body, param_count, source_file = nil) - progress(".") - - @stats.num_methods += 1 class_name = @known_classes[var_name] return unless class_name @@ -578,6 +573,8 @@ class RDoc::Parser::C < RDoc::Parser meth_obj.singleton = %w{singleton_method module_function}.include?(type) + @stats.add_method meth_obj + p_count = (Integer(param_count) rescue -1) if p_count < 0 @@ -622,13 +619,6 @@ class RDoc::Parser::C < RDoc::Parser comment end - def progress(char) - unless @options.quiet - @progress.print(char) - @progress.flush - end - end - ## # Removes lines that are commented out that might otherwise get picked up # when scanning for classes and methods diff --git a/lib/rdoc/parser/f95.rb b/lib/rdoc/parser/f95.rb index 6312bbaaff..fd372b098b 100644 --- a/lib/rdoc/parser/f95.rb +++ b/lib/rdoc/parser/f95.rb @@ -289,11 +289,12 @@ class RDoc::Parser::F95 < RDoc::Parser module_name = module_program_name module_code = module_program_code module_trailing = module_program_trailing - progress "m" - @stats.num_modules += 1 + f9x_module = @top_level.add_module NormalClass, module_name f9x_module.record_location @top_level + @stats.add_module f9x_module + f9x_comment = COMMENTS_ARE_UPPER ? find_comments(pre_comment.join("\n")) + "\n" + module_trailing : module_trailing + "\n" + find_comments(module_code.sub(/^.*$\n/i, '')) @@ -318,7 +319,7 @@ class RDoc::Parser::F95 < RDoc::Parser program_name = module_program_name program_code = module_program_code program_trailing = module_program_trailing - progress "p" + # progress "p" # HACK what stats thingy does this correspond to? program_comment = COMMENTS_ARE_UPPER ? find_comments(pre_comment.join("\n")) + "\n" + program_trailing : program_trailing + "\n" + find_comments(program_code.sub(/^.*$\n/i, '')) @@ -396,7 +397,7 @@ class RDoc::Parser::F95 < RDoc::Parser used_trailing = $3 || "" next if used_trailing =~ /!:nodoc:/ if !container.include_includes?(used_mod_name, @options.ignore_case) - progress "." + # progress "." # HACK what stats thingy does this correspond to? container.add_include Include.new(used_mod_name, "") end if ! (used_list =~ /\,\s*?only\s*?:/i ) @@ -460,7 +461,7 @@ class RDoc::Parser::F95 < RDoc::Parser used_trailing = $3 || "" next if used_trailing =~ /!:nodoc:/ if !container.include_includes?(used_mod_name, @options.ignore_case) - progress "." + # progress "." # HACK what stats thingy does this correspond to? container.add_include Include.new(used_mod_name, "") end end @@ -532,8 +533,9 @@ class RDoc::Parser::F95 < RDoc::Parser type.comment = " Derived Type :: \n" type.comment << args_comment if args_comment type.comment << type_comment if type_comment - progress "t" - @stats.num_methods += 1 + + @stats.add_method type + container.add_method type set_visibility(container, typename, visibility_default, @@public_methods) @@ -607,8 +609,9 @@ class RDoc::Parser::F95 < RDoc::Parser self_comment = find_arguments([defitem.varname], before_contains_code) const_or_var.comment = "" + const_or_var_type + " :: \n" const_or_var.comment << self_comment if self_comment - progress const_or_var_progress - @stats.num_methods += 1 + + @stats.add_method const_or_var_progress + container.add_method const_or_var set_visibility(container, defitem.varname, visibility_default, @@public_methods) @@ -737,8 +740,9 @@ class RDoc::Parser::F95 < RDoc::Parser parse_subprogram(subroutine, subroutine_params, subroutine_comment, subroutine_code, before_contains_code, nil, subroutine_prefix) - progress "s" - @stats.num_methods += 1 + + @stats.add_method subroutine + container.add_method subroutine subroutine_function = subroutine @@ -774,8 +778,8 @@ class RDoc::Parser::F95 < RDoc::Parser function.start_collecting_tokens function.add_token Token.new(1,1).set_text(function_code_org) - progress "f" - @stats.num_methods += 1 + @stats.add_method function + container.add_method function subroutine_function = function @@ -875,8 +879,8 @@ class RDoc::Parser::F95 < RDoc::Parser true, nolink) new_meth.singleton = old_meth.singleton - progress "i" - @stats.num_methods += 1 + @stats.add_method new_meth + container.add_method new_meth set_visibility(container, generic_name, visibility_default, @@public_methods) @@ -939,8 +943,8 @@ class RDoc::Parser::F95 < RDoc::Parser indicated_file, indicated_method.comment) - progress "e" - @stats.num_methods += 1 + @stats.add_method external_method + container.add_method external_method set_visibility(container, generic_name, visibility_default, @@public_methods) if !container.include_requires?(indicated_file, @options.ignore_case) @@ -982,8 +986,9 @@ class RDoc::Parser::F95 < RDoc::Parser if pub_meth["local_name"] new_meth.name = pub_meth["local_name"] end - progress "e" - @stats.num_methods += 1 + + @stats.add_method new_meth + container.add_method new_meth end } @@ -1162,13 +1167,6 @@ EOF nice_lines.shift end - def progress(char) - unless @options.quiet - @progress.print(char) - @progress.flush - end - end - ## # Create method for internal alias @@ -1332,8 +1330,8 @@ EOF comment) new_meth.visibility = alias_item["visibility"] - progress "e" - @stats.num_methods += 1 + @stats.add_method new_meth + alias_item["file_or_module"].add_method(new_meth) if !alias_item["file_or_module"].include_requires?(@file_name, @options.ignore_case) @@ -1368,8 +1366,8 @@ EOF new_meth.name = alias_item["local_name"] end - progress "e" - @stats.num_methods += 1 + @stats.add_method new_meth + alias_item["file_or_module"].add_method new_meth end } diff --git a/lib/rdoc/parser/ruby.rb b/lib/rdoc/parser/ruby.rb index 26757256ad..abbc85bde7 100644 --- a/lib/rdoc/parser/ruby.rb +++ b/lib/rdoc/parser/ruby.rb @@ -1847,8 +1847,6 @@ class RDoc::Parser::Ruby < RDoc::Parser nest = 0 loop do - puts("Call param: #{tk}, #{@scanner.continue} " + - "#{@scanner.lex_state} #{nest}") if $DEBUG_RDOC case tk when TkSEMICOLON break @@ -1872,11 +1870,7 @@ class RDoc::Parser::Ruby < RDoc::Parser res end - def parse_class(container, single, tk, comment, &block) - progress("c") - - @stats.num_classes += 1 - + def parse_class(container, single, tk, comment) container, name_t = get_class_or_module(container) case name_t @@ -1891,22 +1885,21 @@ class RDoc::Parser::Ruby < RDoc::Parser superclass = "" if superclass.empty? end - if single == SINGLE - cls_type = RDoc::SingleClass - else - cls_type = RDoc::NormalClass - end - + cls_type = single == SINGLE ? RDoc::SingleClass : RDoc::NormalClass cls = container.add_class cls_type, name, superclass + + @stats.add_class cls + read_documentation_modifiers cls, RDoc::CLASS_MODIFIERS - cls.record_location(@top_level) - parse_statements(cls) + cls.record_location @top_level + + parse_statements cls cls.comment = comment when TkLSHFT case name = get_class_specification when "self", container.name - parse_statements(container, SINGLE, &block) + parse_statements(container, SINGLE) else other = RDoc::TopLevel.find_class_named(name) unless other @@ -1915,8 +1908,11 @@ class RDoc::Parser::Ruby < RDoc::Parser # other.comment = comment other = RDoc::NormalClass.new "Dummy", nil end + + @stats.add_class other + read_documentation_modifiers other, RDoc::CLASS_MODIFIERS - parse_statements(other, SINGLE, &block) + parse_statements(other, SINGLE) end else @@ -1946,9 +1942,6 @@ class RDoc::Parser::Ruby < RDoc::Parser end loop do - puts "Param: %p, %s %s %s" % - [tk.text, @scanner.continue, @scanner.lex_state, nest] if $DEBUG_RDOC - case tk when TkSEMICOLON break @@ -1982,8 +1975,6 @@ class RDoc::Parser::Ruby < RDoc::Parser end def parse_comment(container, tk, comment) - progress(".") - @stats.num_methods += 1 line_no = tk.line_no column = tk.char_no @@ -1998,6 +1989,8 @@ class RDoc::Parser::Ruby < RDoc::Parser meth = RDoc::GhostMethod.new get_tkread, name meth.singleton = singleton + @stats.add_method meth + meth.start_collecting_tokens indent = TkSPACE.new 1, 1 indent.set_text " " * column @@ -2030,8 +2023,6 @@ class RDoc::Parser::Ruby < RDoc::Parser # Parses a meta-programmed method def parse_meta_method(container, single, tk, comment) - progress(".") - @stats.num_methods += 1 line_no = tk.line_no column = tk.char_no @@ -2063,6 +2054,8 @@ class RDoc::Parser::Ruby < RDoc::Parser meth = RDoc::MetaMethod.new get_tkread, name meth.singleton = singleton + @stats.add_method meth + remove_token_listener self meth.start_collecting_tokens @@ -2105,8 +2098,6 @@ class RDoc::Parser::Ruby < RDoc::Parser # Parses a method def parse_method(container, single, tk, comment) - progress(".") - @stats.num_methods += 1 line_no = tk.line_no column = tk.char_no @@ -2175,6 +2166,8 @@ class RDoc::Parser::Ruby < RDoc::Parser meth.singleton = (single == SINGLE) end + @stats.add_method meth + remove_token_listener self meth.start_collecting_tokens @@ -2239,8 +2232,6 @@ class RDoc::Parser::Ruby < RDoc::Parser nest = 0 loop do - puts "Param: %p, %s %s %s" % - [tk.text, @scanner.continue, @scanner.lex_state, nest] if $DEBUG_RDOC case tk when TkSEMICOLON break @@ -2290,14 +2281,15 @@ class RDoc::Parser::Ruby < RDoc::Parser end def parse_module(container, single, tk, comment) - progress("m") - @stats.num_modules += 1 container, name_t = get_class_or_module(container) -# skip_tkspace + name = name_t.name mod = container.add_module RDoc::NormalModule, name mod.record_location @top_level + + @stats.add_module mod + read_documentation_modifiers mod, RDoc::CLASS_MODIFIERS parse_statements(mod) mod.comment = comment @@ -2422,22 +2414,16 @@ class RDoc::Parser::Ruby < RDoc::Parser when TkUNTIL, TkWHILE then nest += 1 - puts "Found #{tk.class} in #{container.name}, nest = #{nest}, " + - "line #{tk.line_no}" if $DEBUG_RDOC skip_optional_do_after_expression # 'for' is trickier when TkFOR then nest += 1 - puts "Found #{tk.class} in #{container.name}, nest = #{nest}, " + - "line #{tk.line_no}" if $DEBUG_RDOC skip_for_variable skip_optional_do_after_expression when TkCASE, TkDO, TkIF, TkUNLESS, TkBEGIN then nest += 1 - puts "Found #{tk.class} in #{container.name}, nest = #{nest}, " + - "line #{tk.line_no}" if $DEBUG_RDOC when TkIDENTIFIER then if nest == 1 and current_method.nil? then @@ -2470,8 +2456,6 @@ class RDoc::Parser::Ruby < RDoc::Parser when TkEND then nest -= 1 - puts "Found 'end' in #{container.name}, nest = #{nest}, line #{tk.line_no}" if $DEBUG_RDOC - puts "Method = #{current_method.name}" if $DEBUG_RDOC and current_method if nest == 0 then read_documentation_modifiers container, RDoc::CLASS_MODIFIERS container.ongoing_visibility = save_visibility @@ -2641,13 +2625,6 @@ class RDoc::Parser::Ruby < RDoc::Parser tk end - def progress(char) - unless @options.quiet - @progress.print(char) - @progress.flush - end - end - ## # Directives are modifier comments that can appear after class, module, or # method names. For example: @@ -2662,7 +2639,6 @@ class RDoc::Parser::Ruby < RDoc::Parser def read_directive(allowed) tk = get_tk - puts "directive: #{tk.text.inspect}" if $DEBUG_RDOC result = nil if TkCOMMENT === tk if tk.text =~ /\s*:?(\w+):\s*(.*)/ @@ -2769,8 +2745,6 @@ The internal error was: @scanner.instance_eval{@continue = false} loop do - puts("\nWhile: #{tk.text.inspect}, #{@scanner.continue} " \ - "#{@scanner.lex_state} #{nest}") if $DEBUG_RDOC case tk when TkSEMICOLON break diff --git a/lib/rdoc/rdoc.rb b/lib/rdoc/rdoc.rb index 601863ccc9..bc0a32f407 100644 --- a/lib/rdoc/rdoc.rb +++ b/lib/rdoc/rdoc.rb @@ -20,21 +20,24 @@ require 'time' module RDoc ## - # Encapsulate the production of rdoc documentation. Basically - # you can use this as you would invoke rdoc from the command - # line: + # Encapsulate the production of rdoc documentation. Basically you can use + # this as you would invoke rdoc from the command line: # - # rdoc = RDoc::RDoc.new - # rdoc.document(args) + # rdoc = RDoc::RDoc.new + # rdoc.document(args) # - # where _args_ is an array of strings, each corresponding to - # an argument you'd give rdoc on the command line. See rdoc/rdoc.rb - # for details. + # Where +args+ is an array of strings, each corresponding to an argument + # you'd give rdoc on the command line. See rdoc/rdoc.rb for details. class RDoc Generator = Struct.new(:file_name, :class_name, :key) + ## + # Accessor for statistics. Available after each call to parse_files + + attr_reader :stats + ## # This is the list of output generator that we support @@ -57,7 +60,7 @@ module RDoc end def initialize - @stats = Stats.new + @stats = nil end ## @@ -185,6 +188,8 @@ module RDoc # Parse each file on the command line, recursively entering directories. def parse_files(options) + @stats = Stats.new options.verbosity + files = options.files files = ["."] if files.empty? @@ -193,15 +198,14 @@ module RDoc return [] if file_list.empty? file_info = [] - width = file_list.map { |name| name.length }.max + 1 - file_list.each do |fn| - $stderr.printf("\n%*s: ", width, fn) unless options.quiet + file_list.each do |filename| + @stats.add_file filename content = if RUBY_VERSION >= '1.9' then - File.open(fn, "r:ascii-8bit") { |f| f.read } + File.open(filename, "r:ascii-8bit") { |f| f.read } else - File.read fn + File.read filename end if defined? Encoding then @@ -212,12 +216,12 @@ module RDoc end end - top_level = ::RDoc::TopLevel.new fn + top_level = ::RDoc::TopLevel.new filename - parser = ::RDoc::Parser.for top_level, fn, content, options, @stats + parser = ::RDoc::Parser.for top_level, filename, content, options, + @stats file_info << parser.scan - @stats.num_files += 1 end file_info diff --git a/lib/rdoc/ri/descriptions.rb b/lib/rdoc/ri/descriptions.rb index 6a30f51c9b..0d8560323a 100644 --- a/lib/rdoc/ri/descriptions.rb +++ b/lib/rdoc/ri/descriptions.rb @@ -93,8 +93,12 @@ class RDoc::RI::ModuleDescription < RDoc::RI::Description @comment = old.comment else unless old.comment.nil? or old.comment.empty? then - @comment << RDoc::Markup::Flow::RULE.new - @comment.concat old.comment + if @comment.nil? or @comment.empty? then + @comment = old.comment + else + @comment << RDoc::Markup::Flow::RULE.new + @comment.concat old.comment + end end end end diff --git a/lib/rdoc/ri/driver.rb b/lib/rdoc/ri/driver.rb index ecf1bf9f27..dfc5f2f98a 100644 --- a/lib/rdoc/ri/driver.rb +++ b/lib/rdoc/ri/driver.rb @@ -303,6 +303,9 @@ Options may also be set in the 'RI' environment variable. populate_class_cache class_cache, classes, true write_cache class_cache, class_cache_file_path end + + @class_cache = RDoc::RI::Driver::Hash.convert @class_cache + @class_cache end def class_cache_file_path @@ -335,13 +338,13 @@ Options may also be set in the 'RI' environment variable. if File.exist? path and File.mtime(path) >= File.mtime(class_cache_file_path) then - File.open path, 'rb' do |fp| + open path, 'rb' do |fp| cache = Marshal.load fp.read end else class_cache = nil - File.open class_cache_file_path, 'rb' do |fp| + open class_cache_file_path, 'rb' do |fp| class_cache = Marshal.load fp.read end @@ -372,17 +375,34 @@ Options may also be set in the 'RI' environment variable. RDoc::RI::Driver::Hash.convert cache end + ## + # Finds the next ancestor of +orig_klass+ after +klass+. + + def lookup_ancestor(klass, orig_klass) + cache = class_cache[orig_klass] + + return nil unless cache + + ancestors = [orig_klass] + ancestors.push(*cache.includes.map { |inc| inc['name'] }) + ancestors << cache.superclass + + ancestor = ancestors[ancestors.index(klass) + 1] + + return ancestor if ancestor + + lookup_ancestor klass, cache.superclass + end + ## # Finds the method def lookup_method(name, klass) cache = load_cache_for klass - raise NotFoundError, name unless cache + return nil unless cache method = cache[name.gsub('.', '#')] method = cache[name.gsub('.', '::')] unless method - raise NotFoundError, name unless method - method end @@ -435,6 +455,8 @@ Options may also be set in the 'RI' environment variable. desc["class_method_extensions"] = desc.delete "class_methods" end + klass = RDoc::RI::Driver::Hash.convert klass + klass.merge_enums desc klass["sources"] << cdesc end @@ -459,11 +481,25 @@ Options may also be set in the 'RI' environment variable. if class_cache.key? name then display_class name else - meth = nil + klass, = parse_name name + + orig_klass = klass + orig_name = name + + until klass == 'Kernel' do + method = lookup_method name, klass + + break method if method - klass, meth = parse_name name + ancestor = lookup_ancestor klass, orig_klass - method = lookup_method name, klass + break unless ancestor + + name = name.sub klass, ancestor + klass = ancestor + end + + raise NotFoundError, orig_name unless method @display.display_method_info method end @@ -472,6 +508,7 @@ Options may also be set in the 'RI' environment variable. display_class name else methods = select_methods(/^#{name}/) + if methods.size == 0 raise NotFoundError, name elsif methods.size == 1 diff --git a/lib/rdoc/stats.rb b/lib/rdoc/stats.rb index 0fa2dadf61..e18e3c23d7 100644 --- a/lib/rdoc/stats.rb +++ b/lib/rdoc/stats.rb @@ -5,11 +5,49 @@ require 'rdoc' class RDoc::Stats - attr_accessor :num_files, :num_classes, :num_modules, :num_methods + attr_reader :num_classes + attr_reader :num_files + attr_reader :num_methods + attr_reader :num_modules + + def initialize(verbosity = 1) + @num_classes = 0 + @num_files = 0 + @num_methods = 0 + @num_modules = 0 - def initialize - @num_files = @num_classes = @num_modules = @num_methods = 0 @start = Time.now + + @display = case verbosity + when 0 then Quiet.new + when 1 then Normal.new + else Verbose.new + end + end + + def add_alias(as) + @display.print_alias as + @num_methods += 1 + end + + def add_class(klass) + @display.print_class klass + @num_classes += 1 + end + + def add_file(file) + @display.print_file file + @num_files += 1 + end + + def add_method(method) + @display.print_method method + @num_methods += 1 + end + + def add_module(mod) + @display.print_module mod + @num_modules += 1 end def print @@ -17,7 +55,59 @@ class RDoc::Stats puts "Classes: #@num_classes" puts "Modules: #@num_modules" puts "Methods: #@num_methods" - puts "Elapsed: " + sprintf("%0.3fs", Time.now - @start) + puts "Elapsed: " + sprintf("%0.1fs", Time.now - @start) + end + + class Quiet + def print_alias(*) end + def print_class(*) end + def print_file(*) end + def print_method(*) end + def print_module(*) end + end + + class Normal + def print_alias(as) + print 'a' + end + + def print_class(klass) + print 'C' + end + + def print_file(file) + print "\n#{file}: " + end + + def print_method(method) + print 'm' + end + + def print_module(mod) + print 'M' + end + end + + class Verbose + def print_alias(as) + puts "\t\talias #{as.new_name} #{as.old_name}" + end + + def print_class(klass) + puts "\tclass #{klass.full_name}" + end + + def print_file(file) + puts file + end + + def print_method(method) + puts "\t\t#{method.singleton ? '::' : '#'}#{method.name}" + end + + def print_module(mod) + puts "\tmodule #{mod.full_name}" + end end end diff --git a/test/rdoc/test_rdoc_info_formatting.rb b/test/rdoc/test_rdoc_info_formatting.rb index bcc55ddf59..6c024f7454 100644 --- a/test/rdoc/test_rdoc_info_formatting.rb +++ b/test/rdoc/test_rdoc_info_formatting.rb @@ -1,29 +1,25 @@ -$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib/' require 'fileutils' +require 'tmpdir' require 'test/unit' + require 'rdoc/generator/texinfo' -require 'yaml' # From chapter 18 of the Pickaxe 3rd ed. and the TexInfo manual. class TestRdocInfoFormatting < Test::Unit::TestCase - OUTPUT_DIR = "/tmp/rdoc-#{$$}" - def setup - # supress stdout - $stdout = File.new('/dev/null','w') - $stderr = File.new('/dev/null','w') + @output_dir = File.join Dir.tmpdir, "test_rdoc_info_formatting_#{$$}" + @output_file = File.join @output_dir, 'rdoc.texinfo' - RDoc::RDoc.new.document(['--fmt=texinfo', + RDoc::RDoc.new.document(['--fmt=texinfo', '--quiet', File.expand_path(__FILE__), - "--op=#{OUTPUT_DIR}"]) - @text = File.read(OUTPUT_DIR + '/rdoc.texinfo') + "--op=#{@output_dir}"]) + @text = File.read @output_file + # File.open('rdoc.texinfo', 'w') { |f| f.puts @text } end def teardown - $stdout = STDOUT - $stderr = STDERR - FileUtils.rm_rf OUTPUT_DIR + FileUtils.rm_rf @output_dir end # Make sure tags like *this* do not make HTML diff --git a/test/rdoc/test_rdoc_info_sections.rb b/test/rdoc/test_rdoc_info_sections.rb index 4cc982613e..cceba186c1 100644 --- a/test/rdoc/test_rdoc_info_sections.rb +++ b/test/rdoc/test_rdoc_info_sections.rb @@ -76,8 +76,8 @@ class TestRdocInfoSections < Test::Unit::TestCase # if system "makeinfo --version > /dev/null" # def test_compiles_to_info -# makeinfo_output = `cd #{OUTPUT_DIR} && makeinfo rdoc.texinfo` -# assert(File.exist?(File.join(OUTPUT_DIR, 'rdoc.info')), +# makeinfo_output = `cd #{@output_dir} && makeinfo rdoc.texinfo` +# assert(File.exist?(File.join(@output_dir, 'rdoc.info')), # "Info file was not compiled: #{makeinfo_output}") # end # end diff --git a/test/rdoc/test_rdoc_parser_c.rb b/test/rdoc/test_rdoc_parser_c.rb index a52018f372..fd750070d8 100644 --- a/test/rdoc/test_rdoc_parser_c.rb +++ b/test/rdoc/test_rdoc_parser_c.rb @@ -18,10 +18,8 @@ class TestRdocParserC < Test::Unit::TestCase @top_level = RDoc::TopLevel.new filename @fn = filename - @options = RDoc::Options.new Hash.new - @stats = RDoc::Stats.new - - @progress = StringIO.new + @options = RDoc::Options.new + @stats = RDoc::Stats.new 0 end def teardown @@ -253,9 +251,7 @@ Init_Foo(void) { end def util_parser(content) - parser = RDoc::Parser::C.new @top_level, @fn, content, @options, @stats - parser.progress = @progress - parser + RDoc::Parser::C.new @top_level, @fn, content, @options, @stats end end diff --git a/test/rdoc/test_rdoc_parser_ruby.rb b/test/rdoc/test_rdoc_parser_ruby.rb index 2bf659e566..46c95bd061 100644 --- a/test/rdoc/test_rdoc_parser_ruby.rb +++ b/test/rdoc/test_rdoc_parser_ruby.rb @@ -13,11 +13,9 @@ class TestRdocParserRuby < Test::Unit::TestCase @filename = @tempfile.path util_toplevel - @options = RDoc::Options.new Hash.new + @options = RDoc::Options.new @options.quiet = true - @stats = RDoc::Stats.new - - @progress = StringIO.new + @stats = RDoc::Stats.new 0 end def teardown @@ -132,6 +130,84 @@ class TestRdocParserRuby < Test::Unit::TestCase assert_equal 'hi', @options.title end + def test_parse_class + comment = "##\n# my method\n" + + util_parser 'class Foo; end' + + tk = @parser.get_tk + + @parser.parse_class @top_level, RDoc::Parser::Ruby::NORMAL, tk, comment + + foo = @top_level.classes.first + assert_equal 'Foo', foo.full_name + assert_equal comment, foo.comment + end + + def test_parse_class_nested_superclass + foo = RDoc::NormalModule.new 'Foo' + foo.parent = @top_level + + util_parser "class Bar < Super\nend" + + tk = @parser.get_tk + + @parser.parse_class foo, RDoc::Parser::Ruby::NORMAL, tk, '' + + bar = foo.classes.first + assert_equal 'Super', bar.superclass + end + + def test_parse_comment + content = <<-EOF +class Foo + ## + # :method: my_method + # my method comment + +end + EOF + klass = RDoc::NormalClass.new 'Foo' + klass.parent = @top_level + + comment = "##\n# :method: foo\n# my method\n" + + util_parser "\n" + + tk = @parser.get_tk + + @parser.parse_comment klass, tk, comment + + foo = klass.method_list.first + assert_equal 'foo', foo.name + assert_equal comment, foo.comment + + assert_equal [], foo.aliases + assert_equal nil, foo.block_params + assert_equal nil, foo.call_seq + assert_equal nil, foo.is_alias_for + assert_equal nil, foo.viewer + assert_equal true, foo.document_children + assert_equal true, foo.document_self + assert_equal '', foo.params + assert_equal false, foo.done_documenting + assert_equal false, foo.dont_rename_initialize + assert_equal false, foo.force_documentation + assert_equal klass, foo.parent + assert_equal false, foo.singleton + assert_equal :public, foo.visibility + assert_equal "\n", foo.text + assert_equal klass.current_section, foo.section + + stream = [ + tk(:COMMENT, 1, 1, nil, "# File #{@top_level.file_absolute_name}, line 1"), + RDoc::Parser::Ruby::NEWLINE_TOKEN, + tk(:SPACE, 1, 1, nil, ''), + ] + + assert_equal stream, foo.token_stream + end + def test_parse_meta_method klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level @@ -301,54 +377,19 @@ class TestRdocParserRuby < Test::Unit::TestCase assert_equal stream, foo.token_stream end - def test_parse_statements_comment - content = <<-EOF -class Foo - ## - # :method: my_method - # my method comment - -end - EOF - klass = RDoc::NormalClass.new 'Foo' - klass.parent = @top_level - - comment = "##\n# :method: foo\n# my method\n" - - util_parser "\n" - - tk = @parser.get_tk - - @parser.parse_comment klass, tk, comment + def test_parse_statements_class_nested + comment = "##\n# my method\n" - foo = klass.method_list.first - assert_equal 'foo', foo.name - assert_equal comment, foo.comment + util_parser "module Foo\n#{comment}class Bar\nend\nend" - assert_equal [], foo.aliases - assert_equal nil, foo.block_params - assert_equal nil, foo.call_seq - assert_equal nil, foo.is_alias_for - assert_equal nil, foo.viewer - assert_equal true, foo.document_children - assert_equal true, foo.document_self - assert_equal '', foo.params - assert_equal false, foo.done_documenting - assert_equal false, foo.dont_rename_initialize - assert_equal false, foo.force_documentation - assert_equal klass, foo.parent - assert_equal false, foo.singleton - assert_equal :public, foo.visibility - assert_equal "\n", foo.text - assert_equal klass.current_section, foo.section + @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL, nil, '' - stream = [ - tk(:COMMENT, 1, 1, nil, "# File #{@top_level.file_absolute_name}, line 1"), - RDoc::Parser::Ruby::NEWLINE_TOKEN, - tk(:SPACE, 1, 1, nil, ''), - ] + foo = @top_level.modules.first + assert_equal 'Foo', foo.full_name, 'module Foo' - assert_equal stream, foo.token_stream + bar = foo.classes.first + assert_equal 'Foo::Bar', bar.full_name, 'class Foo::Bar' + assert_equal comment, bar.comment end def test_parse_statements_identifier_meta_method @@ -487,8 +528,6 @@ end def util_parser(content) @parser = RDoc::Parser::Ruby.new @top_level, @filename, content, @options, @stats - @parser.progress = @progress - @parser end def util_toplevel diff --git a/test/rdoc/test_rdoc_ri_driver.rb b/test/rdoc/test_rdoc_ri_driver.rb index 5db831915a..cddd4e60d1 100644 --- a/test/rdoc/test_rdoc_ri_driver.rb +++ b/test/rdoc/test_rdoc_ri_driver.rb @@ -41,11 +41,7 @@ class TestRDocRIDriver < Test::Unit::TestCase def test_lookup_method_class_missing def @driver.load_cache_for(klassname) end - e = assert_raise RDoc::RI::Driver::NotFoundError do - @driver.lookup_method 'Foo#bar', 'Foo' - end - - assert_equal 'Nothing known about Foo#bar', e.message + assert_nil @driver.lookup_method('Foo#bar', 'Foo') end def test_lookup_method_dot_instance @@ -67,11 +63,7 @@ class TestRDocRIDriver < Test::Unit::TestCase def test_lookup_method_method_missing def @driver.load_cache_for(klassname) {} end - e = assert_raise RDoc::RI::Driver::NotFoundError do - @driver.lookup_method 'Foo#bar', 'Foo' - end - - assert_equal 'Nothing known about Foo#bar', e.message + assert_nil @driver.lookup_method('Foo#bar', 'Foo') end def test_parse_name -- cgit v1.2.3