diff options
author | drbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2010-12-20 03:22:49 +0000 |
---|---|---|
committer | drbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2010-12-20 03:22:49 +0000 |
commit | 2ef9c50c6e405717d06362787c4549ca4f1c6485 (patch) | |
tree | ee99486567461dd5796f3d6edcc9e204187f2666 /lib/rdoc/class_module.rb | |
parent | d7effd506f5b91a636f2e6452ef1946b923007c7 (diff) |
Import RDoc 3
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@30249 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/rdoc/class_module.rb')
-rw-r--r-- | lib/rdoc/class_module.rb | 258 |
1 files changed, 236 insertions, 22 deletions
diff --git a/lib/rdoc/class_module.rb b/lib/rdoc/class_module.rb index 16b85d7918..1e75699ffa 100644 --- a/lib/rdoc/class_module.rb +++ b/lib/rdoc/class_module.rb @@ -8,31 +8,114 @@ class RDoc::ClassModule < RDoc::Context MARSHAL_VERSION = 0 # :nodoc: - attr_accessor :diagram + ## + # Constants that are aliases for this class or module + + attr_accessor :constant_aliases + + attr_accessor :diagram # :nodoc: ## - # Creates a new ClassModule with +name+ with optional +superclass+ + # Class or module this constant is an alias for - def initialize(name, superclass = 'Object') - @diagram = nil - @full_name = nil - @name = name - @superclass = superclass + attr_accessor :is_alias_for + + ## + # Return a RDoc::ClassModule of class +class_type+ that is a copy + # of module +module+. Used to promote modules to classes. + + def self.from_module(class_type, mod) + klass = class_type.new(mod.name) + klass.comment = mod.comment + klass.parent = mod.parent + klass.section = mod.section + klass.viewer = mod.viewer + + klass.attributes.concat mod.attributes + klass.method_list.concat mod.method_list + klass.aliases.concat mod.aliases + klass.external_aliases.concat mod.external_aliases + klass.constants.concat mod.constants + klass.includes.concat mod.includes + + klass.methods_hash.update mod.methods_hash + klass.constants_hash.update mod.constants_hash + + klass.current_section = mod.current_section + klass.in_files.concat mod.in_files + klass.sections.concat mod.sections + klass.unmatched_alias_lists = mod.unmatched_alias_lists + klass.current_section = mod.current_section + klass.visibility = mod.visibility + + klass.classes_hash.update mod.classes_hash + klass.modules_hash.update mod.modules_hash + klass.metadata.update mod.metadata + + klass.document_self = mod.received_nodoc ? nil : mod.document_self + klass.document_children = mod.document_children + klass.force_documentation = mod.force_documentation + klass.done_documenting = mod.done_documenting + + # update the parent of all children + + (klass.attributes + + klass.method_list + + klass.aliases + + klass.external_aliases + + klass.constants + + klass.includes + + klass.classes + + klass.modules).each do |obj| + obj.parent = klass + obj.full_name = nil + end + + klass + end + + ## + # Creates a new ClassModule with +name+ with optional +superclass+ + # + # This is a constructor for subclasses, and must never be called directly. + + def initialize(name, superclass = nil) + @constant_aliases = [] + @diagram = nil + @is_alias_for = nil + @name = name + @superclass = superclass super() end ## - # Ancestors list for this ClassModule (abstract) + # Ancestors list for this ClassModule: the list of included modules + # (classes will add their superclass if any). + # + # Returns the included classes or modules, not the includes + # themselves. The returned values are either String or + # RDoc::NormalModule instances (see RDoc::Include#module). + # + # The values are returned in reverse order of their inclusion, + # which is the order suitable for searching methods/attributes + # in the ancestors. The superclass, if any, comes last. def ancestors - raise NotImplementedError + includes.map { |i| i.module }.reverse + end + + ## + # Clears the comment. Used by the ruby parser. + + def clear_comment + @comment = '' end ## # Appends +comment+ to the current comment, but separated by a rule. Works # more like <tt>+=</tt>. - def comment=(comment) + def comment= comment return if comment.empty? comment = "#{@comment}\n---\n#{normalize_comment comment}" unless @@ -42,9 +125,34 @@ class RDoc::ClassModule < RDoc::Context end ## + # Prepares this ClassModule for use by a generator. + # + # See RDoc::TopLevel::complete + + def complete min_visibility + update_aliases + remove_nodoc_children + update_includes + remove_invisible min_visibility + end + + ## + # Looks for a symbol in the #ancestors. See Context#find_local_symbol. + + def find_ancestor_local_symbol symbol + ancestors.each do |m| + next if m.is_a?(String) + res = m.find_local_symbol(symbol) + return res if res + end + + nil + end + + ## # Finds a class or module with +name+ in this namespace or its descendents - def find_class_named(name) + def find_class_named name return self if full_name == name return self if @name == name @@ -65,14 +173,8 @@ class RDoc::ClassModule < RDoc::Context end end - ## - # 'module' or 'class' - - def type - module? ? 'module' : 'class' - end - def marshal_dump # :nodoc: + # TODO must store the singleton attribute attrs = attributes.sort.map do |attr| [attr.name, attr.rw] end @@ -106,10 +208,13 @@ class RDoc::ClassModule < RDoc::Context end def marshal_load array # :nodoc: + # TODO must restore the singleton attribute initialize_methods_etc @document_self = true @done_documenting = false @current_section = nil + @parent = nil + @visibility = nil @name = array[1] @full_name = array[2] @@ -184,6 +289,15 @@ class RDoc::ClassModule < RDoc::Context end ## + # Allows overriding the initial name. + # + # Used for modules and classes that are constant aliases. + + def name= new_name + @name = new_name + end + + ## # Path to this class or module def path @@ -191,11 +305,51 @@ class RDoc::ClassModule < RDoc::Context end ## + # Name to use to generate the url: + # modules and classes that are aliases for another + # module or classe return the name of the latter. + + def name_for_path + is_alias_for ? is_alias_for.full_name : full_name + end + + ## + # Returns the classes and modules that are not constants + # aliasing another class or module. For use by formatters + # only (caches its result). + + def non_aliases + @non_aliases ||= classes_and_modules.reject { |cm| cm.is_alias_for } + end + + ## + # Updates the child modules or classes of class/module +parent+ by + # deleting the ones that have been removed from the documentation. + # + # +parent_hash+ is either <tt>parent.modules_hash</tt> or + # <tt>parent.classes_hash</tt> and +all_hash+ is ::all_modules_hash or + # ::all_classes_hash. + + def remove_nodoc_children + prefix = self.full_name + '::' + + modules_hash.each_key do |name| + full_name = prefix + name + modules_hash.delete name unless RDoc::TopLevel.all_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] + 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_from(@superclass, parent) || @superclass + RDoc::TopLevel.find_class_named(@superclass) || @superclass end ## @@ -203,12 +357,72 @@ class RDoc::ClassModule < RDoc::Context def superclass=(superclass) raise NoMethodError, "#{full_name} is a module" if module? - - @superclass = superclass if @superclass.nil? or @superclass == 'Object' + @superclass = superclass end def to_s # :nodoc: - "#{self.class}: #{full_name} #{@comment} #{super}" + if is_alias_for then + "#{self.class.name} #{self.full_name} -> #{is_alias_for}" + else + super + end + end + + ## + # 'module' or 'class' + + def type + module? ? 'module' : 'class' + end + + ## + # Updates the child modules & classes by replacing the ones that are + # 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 + # 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. + # + # Formatters can use the #non_aliases method to retrieve children that + # are not aliases, for instance to list the namespace content, since + # the aliased modules are included in the constants of the class/module, + # that are listed separately. + + def update_aliases + constants.each do |const| + 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 + 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 + modules_hash[const.name] = cm_alias + else + RDoc::TopLevel.all_classes_hash[cm_alias.full_name] = cm_alias + classes_hash[const.name] = cm_alias + end + + cm.aliases << cm_alias + end + end + + ## + # Deletes from #includes those whose module has been removed from the + # documentation. + #-- + # FIXME: includes are not reliably removed, see _possible_bug test case + + def update_includes + includes.reject! do |include| + mod = include.module + !(String === mod) && RDoc::TopLevel.all_modules_hash[mod.full_name].nil? + end end end |