diff options
Diffstat (limited to 'lib/rdoc/class_module.rb')
-rw-r--r-- | lib/rdoc/class_module.rb | 267 |
1 files changed, 227 insertions, 40 deletions
diff --git a/lib/rdoc/class_module.rb b/lib/rdoc/class_module.rb index 27066d8bd7..04f0132b7d 100644 --- a/lib/rdoc/class_module.rb +++ b/lib/rdoc/class_module.rb @@ -1,5 +1,3 @@ -require 'rdoc/context' - ## # ClassModule is the base class for objects representing either a class or a # module. @@ -13,8 +11,17 @@ class RDoc::ClassModule < RDoc::Context # * Added file to constants # * Added file to includes # * Added file to methods - - MARSHAL_VERSION = 1 # :nodoc: + # 2:: + # RDoc 3.13 + # * Added extends + # 3:: + # RDoc 4.0 + # * Added sections + # * Added in_files + # * Added parent name + # * Complete Constant dump + + MARSHAL_VERSION = 3 # :nodoc: ## # Constants that are aliases for this class or module @@ -56,6 +63,7 @@ class RDoc::ClassModule < RDoc::Context klass.external_aliases.concat mod.external_aliases klass.constants.concat mod.constants klass.includes.concat mod.includes + klass.extends.concat mod.extends klass.methods_hash.update mod.methods_hash klass.constants_hash.update mod.constants_hash @@ -84,6 +92,7 @@ class RDoc::ClassModule < RDoc::Context klass.external_aliases + klass.constants + klass.includes + + klass.extends + klass.classes + klass.modules).each do |obj| obj.parent = klass @@ -115,16 +124,32 @@ class RDoc::ClassModule < RDoc::Context # across multiple runs. def add_comment comment, location - return if comment.empty? or not document_self + return unless document_self original = comment - comment = normalize_comment comment + comment = case comment + when RDoc::Comment then + comment.normalize + else + normalize_comment comment + end @comment_location << [comment, location] self.comment = original end + def add_things my_things, other_things # :nodoc: + other_things.each do |group, things| + my_things[group].each { |thing| yield false, thing } if + my_things.include? group + + things.each do |thing| + yield true, thing + end + end + end + ## # Ancestors list for this ClassModule: the list of included modules # (classes will add their superclass if any). @@ -142,6 +167,11 @@ class RDoc::ClassModule < RDoc::Context end ## + # Ancestors of this class or module only + + alias direct_ancestors ancestors + + ## # Clears the comment. Used by the ruby parser. def clear_comment @@ -155,9 +185,13 @@ class RDoc::ClassModule < RDoc::Context # more like <tt>+=</tt>. def comment= comment - return if comment.empty? + comment = case comment + when RDoc::Comment then + comment.normalize + else + normalize_comment comment + end - comment = normalize_comment comment comment = "#{@comment}\n---\n#{comment}" unless @comment.empty? super comment @@ -166,7 +200,7 @@ class RDoc::ClassModule < RDoc::Context ## # Prepares this ClassModule for use by a generator. # - # See RDoc::TopLevel::complete + # See RDoc::Store#complete def complete min_visibility update_aliases @@ -176,12 +210,22 @@ class RDoc::ClassModule < RDoc::Context end ## + # Does this ClassModule or any of its methods have document_self set? + + def document_self_or_methods + document_self || method_list.any?{ |m| m.document_self } + end + + ## # Iterates the ancestors of this class or module for which an # RDoc::ClassModule exists. def each_ancestor # :yields: module + return enum_for __method__ unless block_given? + ancestors.each do |mod| next if String === mod + next if self == mod yield mod end end @@ -215,8 +259,8 @@ class RDoc::ClassModule < RDoc::Context # Return the fully qualified name of this class or module def full_name - @full_name ||= if RDoc::ClassModule === @parent then - "#{@parent.full_name}::#{@name}" + @full_name ||= if RDoc::ClassModule === parent then + "#{parent.full_name}::#{@name}" else @name end @@ -250,13 +294,20 @@ class RDoc::ClassModule < RDoc::Context @superclass, parse(@comment_location), attrs, - constants.map do |const| - [const.name, parse(const.comment), const.file_name] - end, + constants, includes.map do |incl| [incl.name, parse(incl.comment), incl.file_name] end, method_types, + extends.map do |ext| + [ext.name, parse(ext.comment), ext.file_name] + end, + @sections.values, + @in_files.map do |tl| + tl.absolute_name + end, + parent.full_name, + parent.class, ] end @@ -268,6 +319,8 @@ class RDoc::ClassModule < RDoc::Context @parent = nil @temporary_section = nil @visibility = nil + @classes = {} + @modules = {} @name = array[1] @full_name = array[2] @@ -291,9 +344,14 @@ class RDoc::ClassModule < RDoc::Context attr.record_location RDoc::TopLevel.new file end - array[6].each do |name, comment, file| - const = add_constant RDoc::Constant.new(name, nil, comment) - const.record_location RDoc::TopLevel.new file + array[6].each do |constant, comment, file| + case constant + when RDoc::Constant then + add_constant constant + else + constant = add_constant RDoc::Constant.new(constant, nil, comment) + constant.record_location RDoc::TopLevel.new file + end end array[7].each do |name, comment, file| @@ -313,6 +371,27 @@ class RDoc::ClassModule < RDoc::Context end end end + + array[9].each do |name, comment, file| + ext = add_extend RDoc::Extend.new(name, comment) + ext.record_location RDoc::TopLevel.new file + end if array[9] # Support Marshal version 1 + + sections = (array[10] || []).map do |section| + [section.title, section] + end + + @sections = Hash[*sections.flatten] + @current_section = add_section nil + + @in_files = [] + + (array[11] || []).each do |filename| + record_location RDoc::TopLevel.new filename + end + + @parent_name = array[12] + @parent_class = array[13] end ## @@ -321,6 +400,9 @@ class RDoc::ClassModule < RDoc::Context # The data in +class_module+ is preferred over the receiver. def merge class_module + @parent = class_module.parent + @parent_name = class_module.parent_name + other_document = parse class_module.comment_location if other_document then @@ -360,6 +442,18 @@ class RDoc::ClassModule < RDoc::Context end end + @includes.uniq! # clean up + + merge_collections extends, cm.extends, other_files do |add, ext| + if add then + add_extend ext + else + @extends.delete ext + end + end + + @extends.uniq! # clean up + merge_collections method_list, cm.method_list, other_files do |add, meth| if add then add_method meth @@ -369,6 +463,8 @@ class RDoc::ClassModule < RDoc::Context end end + merge_sections cm + self end @@ -391,22 +487,46 @@ class RDoc::ClassModule < RDoc::Context my_things = mine. group_by { |thing| thing.file } other_things = other.group_by { |thing| thing.file } - my_things.delete_if do |file, things| - next false unless other_files.include? file + remove_things my_things, other_files, &block + add_things my_things, other_things, &block + end - things.each do |thing| - yield false, thing - end + ## + # Merges the comments in this ClassModule with the comments in the other + # ClassModule +cm+. - true + def merge_sections cm # :nodoc: + my_sections = sections.group_by { |section| section.title } + other_sections = cm.sections.group_by { |section| section.title } + + other_files = cm.in_files + + remove_things my_sections, other_files do |_, section| + @sections.delete section.title end - other_things.each do |file, things| - my_things[file].each { |thing| yield false, thing } if - my_things.include?(file) + other_sections.each do |group, sections| + if my_sections.include? group + my_sections[group].each do |my_section| + other_section = cm.sections_hash[group] - things.each do |thing| - yield true, thing + my_comments = my_section.comments + other_comments = other_section.comments + + other_files = other_section.in_files + + merge_collections my_comments, other_comments, other_files do |add, comment| + if add then + my_section.add_comment comment + else + my_section.remove_comment comment + end + end + end + else + sections.each do |section| + add_section group, section.comments + end end end end @@ -438,11 +558,15 @@ class RDoc::ClassModule < RDoc::Context when Array then docs = comment_location.map do |comment, location| doc = super comment - doc.file = location.absolute_name + doc.file = location doc end RDoc::Markup::Document.new(*docs) + when RDoc::Comment then + doc = super comment_location.text, comment_location.format + doc.file = comment_location.location + doc when RDoc::Markup::Document then return comment_location else @@ -451,10 +575,10 @@ class RDoc::ClassModule < RDoc::Context end ## - # Path to this class or module + # Path to this class or module for use with HTML generator output. def path - http_url RDoc::RDoc.current.generator.class_dir + http_url @store.rdoc.generator.class_dir end ## @@ -488,21 +612,61 @@ class RDoc::ClassModule < RDoc::Context modules_hash.each_key do |name| full_name = prefix + name - modules_hash.delete name unless RDoc::TopLevel.all_modules_hash[full_name] + modules_hash.delete name unless @store.modules_hash[full_name] end classes_hash.each_key do |name| full_name = prefix + name - classes_hash.delete name unless RDoc::TopLevel.all_classes_hash[full_name] + classes_hash.delete name unless @store.classes_hash[full_name] end end + def remove_things my_things, other_files # :nodoc: + my_things.delete_if do |file, things| + next false unless other_files.include? file + + things.each do |thing| + yield false, thing + end + + true + end + end + + ## + # Search record used by RDoc::Generator::JsonIndex + + def search_record + [ + name, + full_name, + full_name, + '', + path, + '', + snippet(@comment_location), + ] + end + + ## + # Sets the store for this class or module and its contained code objects. + + def store= store + super + + @attributes .each do |attr| attr.store = store end + @constants .each do |const| const.store = store end + @includes .each do |incl| incl.store = store end + @extends .each do |ext| ext.store = store end + @method_list.each do |meth| meth.store = store end + end + ## # Get the superclass of this class. Attempts to retrieve the superclass # object, returns the name if it is not known. def superclass - RDoc::TopLevel.find_class_named(@superclass) || @superclass + @store.find_class_named(@superclass) || @superclass end ## @@ -533,7 +697,7 @@ class RDoc::ClassModule < RDoc::Context # aliases through a constant. # # The aliased module/class is replaced in the children and in - # RDoc::TopLevel::all_modules_hash or RDoc::TopLevel::all_classes_hash + # RDoc::Store#modules_hash or RDoc::Store#classes_hash # by a copy that has <tt>RDoc::ClassModule#is_alias_for</tt> set to # the aliased module/class, and this copy is added to <tt>#aliases</tt> # of the aliased module/class. @@ -548,16 +712,21 @@ class RDoc::ClassModule < RDoc::Context next unless cm = const.is_alias_for cm_alias = cm.dup cm_alias.name = const.name - cm_alias.parent = self - cm_alias.full_name = nil # force update for new parent + + # Don't move top-level aliases under Object, they look ugly there + unless RDoc::TopLevel === cm_alias.parent then + cm_alias.parent = self + cm_alias.full_name = nil # force update for new parent + end + cm_alias.aliases.clear cm_alias.is_alias_for = cm if cm.module? then - RDoc::TopLevel.all_modules_hash[cm_alias.full_name] = cm_alias + @store.modules_hash[cm_alias.full_name] = cm_alias modules_hash[const.name] = cm_alias else - RDoc::TopLevel.all_classes_hash[cm_alias.full_name] = cm_alias + @store.classes_hash[cm_alias.full_name] = cm_alias classes_hash[const.name] = cm_alias end @@ -574,8 +743,26 @@ class RDoc::ClassModule < RDoc::Context def update_includes includes.reject! do |include| mod = include.module - !(String === mod) && RDoc::TopLevel.all_modules_hash[mod.full_name].nil? + !(String === mod) && @store.modules_hash[mod.full_name].nil? end + + includes.uniq! + end + + ## + # Deletes from #extends those whose module has been removed from the + # documentation. + #-- + # FIXME: like update_includes, extends are not reliably removed + + def update_extends + extends.reject! do |ext| + mod = ext.module + + !(String === mod) && @store.modules_hash[mod.full_name].nil? + end + + extends.uniq! end end |