aboutsummaryrefslogtreecommitdiffstats
path: root/lib/rdoc/class_module.rb
diff options
context:
space:
mode:
authordrbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2010-12-20 03:22:49 +0000
committerdrbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2010-12-20 03:22:49 +0000
commit2ef9c50c6e405717d06362787c4549ca4f1c6485 (patch)
treeee99486567461dd5796f3d6edcc9e204187f2666 /lib/rdoc/class_module.rb
parentd7effd506f5b91a636f2e6452ef1946b923007c7 (diff)
downloadruby-2ef9c50c6e405717d06362787c4549ca4f1c6485.tar.gz
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.rb258
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