summaryrefslogtreecommitdiff
path: root/lib/rdoc/context.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/context.rb
parentd7effd506f5b91a636f2e6452ef1946b923007c7 (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/context.rb')
-rw-r--r--lib/rdoc/context.rb711
1 files changed, 495 insertions, 216 deletions
diff --git a/lib/rdoc/context.rb b/lib/rdoc/context.rb
index d55c5a9164..c424ef1676 100644
--- a/lib/rdoc/context.rb
+++ b/lib/rdoc/context.rb
@@ -15,17 +15,12 @@ class RDoc::Context < RDoc::CodeObject
TYPES = %w[class instance]
##
- # Method visibilities
-
- VISIBILITIES = [:public, :protected, :private]
-
- ##
- # Aliased methods
+ # Class/module aliases
attr_reader :aliases
##
- # attr* methods
+ # All attr* methods
attr_reader :attributes
@@ -37,7 +32,7 @@ class RDoc::Context < RDoc::CodeObject
##
# Current section of documentation
- attr_reader :current_section
+ attr_accessor :current_section
##
# Files this context is found in
@@ -70,19 +65,37 @@ class RDoc::Context < RDoc::CodeObject
attr_reader :sections
##
- # Aliases that haven't been resolved to a method
+ # Hash <tt>old_name => [aliases]</tt>, for aliases
+ # that haven't (yet) been resolved to a method/attribute.
+ # (Not to be confused with the aliases of the context.)
attr_accessor :unmatched_alias_lists
##
+ # Aliases that could not eventually be resolved.
+
+ attr_reader :external_aliases
+
+ ##
# Current visibility of this context
- attr_reader :visibility
+ attr_accessor :visibility
+
+ ##
+ # Hash of registered methods. Attributes are also registered here,
+ # twice if they are RW.
+
+ attr_reader :methods_hash
+
+ ##
+ # Hash of registered constants.
+
+ attr_reader :constants_hash
##
# A per-comment section of documentation like:
#
- # # :SECTION: The title
+ # # :section: The title
# # The body
class Section
@@ -137,14 +150,12 @@ class RDoc::Context < RDoc::CodeObject
end
##
- # Set the comment for this section from the original comment block If
+ # Set the comment for this section from the original comment block. If
# the first line contains :section:, strip it and use the rest.
# Otherwise remove lines up to the line containing :section:, and look
# for those lines again at the end and remove them. This lets us write
#
- # # blah blah blah
- # #
- # # :SECTION: The title
+ # # :section: The title
# # The body
def set_comment(comment)
@@ -169,7 +180,7 @@ class RDoc::Context < RDoc::CodeObject
end
##
- # Creates an unnamed empty context with public visibility
+ # Creates an unnamed empty context with public current visibility
def initialize
super
@@ -184,16 +195,10 @@ class RDoc::Context < RDoc::CodeObject
@current_section = Section.new self, nil, nil
@sections = [@current_section]
- initialize_methods_etc
- initialize_classes_and_modules
- end
-
- ##
- # Sets the defaults for classes and modules
-
- def initialize_classes_and_modules
@classes = {}
@modules = {}
+
+ initialize_methods_etc
end
##
@@ -206,10 +211,14 @@ class RDoc::Context < RDoc::CodeObject
@requires = []
@includes = []
@constants = []
+ @external_aliases = []
# This Hash maps a method name to a list of unmatched aliases (aliases of
# a method not yet encountered).
@unmatched_alias_lists = {}
+
+ @methods_hash = {}
+ @constants_hash = {}
end
##
@@ -222,14 +231,18 @@ class RDoc::Context < RDoc::CodeObject
##
# Adds +an_alias+ that is automatically resolved
- def add_alias(an_alias)
- meth = find_instance_method_named(an_alias.old_name)
+ def add_alias an_alias
+ return an_alias unless @document_self
+
+ method_attr = find_method(an_alias.old_name, an_alias.singleton) ||
+ find_attribute(an_alias.old_name, an_alias.singleton)
- if meth then
- add_alias_impl an_alias, meth
+ if method_attr then
+ method_attr.add_alias an_alias, self
else
- add_to @aliases, an_alias
- unmatched_alias_list = @unmatched_alias_lists[an_alias.old_name] ||= []
+ add_to @external_aliases, an_alias
+ unmatched_alias_list =
+ @unmatched_alias_lists[an_alias.pretty_old_name] ||= []
unmatched_alias_list.push an_alias
end
@@ -237,175 +250,279 @@ class RDoc::Context < RDoc::CodeObject
end
##
- # Turns +an_alias+ into an AnyMethod that points to +meth+
-
- def add_alias_impl(an_alias, meth)
- new_meth = RDoc::AnyMethod.new an_alias.text, an_alias.new_name
- new_meth.is_alias_for = meth
- new_meth.singleton = meth.singleton
- new_meth.params = meth.params
-
- new_meth.comment = an_alias.comment
-
- meth.add_alias new_meth
-
- add_method new_meth
-
- # aliases don't use ongoing visibility
- new_meth.visibility = meth.visibility
-
- new_meth
- end
+ # Adds +attribute+ if not already there. If it is (as method(s) or attribute),
+ # updates the comment if it was empty.
+ #
+ # The attribute is registered only if it defines a new method.
+ # For instance, <tt>attr_reader :foo</tt> will not be registered
+ # if method +foo+ exists, but <tt>attr_accessor :foo</tt> will be registered
+ # if method +foo+ exists, but <tt>foo=</tt> does not.
+
+ def add_attribute attribute
+ return attribute unless @document_self
+
+ # mainly to check for redefinition of an attribute as a method
+ # TODO find a policy for 'attr_reader :foo' + 'def foo=()'
+ register = false
+
+ if attribute.rw.index('R') then
+ key = attribute.pretty_name
+ known = @methods_hash[key]
+ if known then
+ known.comment = attribute.comment if known.comment.empty?
+ else
+ @methods_hash[key] = attribute
+ register = true
+ end
+ end
- ##
- # Adds +attribute+
+ if attribute.rw.index('W')
+ key = attribute.pretty_name << '='
+ known = @methods_hash[key]
+ if known then
+ known.comment = attribute.comment if known.comment.empty?
+ else
+ @methods_hash[key] = attribute
+ register = true
+ end
+ end
- def add_attribute(attribute)
- add_to @attributes, attribute
+ if register then
+ attribute.visibility = @visibility
+ add_to @attributes, attribute
+ resolve_aliases attribute
+ end
end
##
- # Adds a class named +name+ with +superclass+.
+ # Adds a class named +given_name+ with +superclass+.
+ #
+ # Both +given_name+ and +superclass+ may contain '::', and are
+ # interpreted relative to the +self+ context. This allows handling correctly
+ # examples like these:
+ # class RDoc::Gauntlet < Gauntlet
+ # module Mod
+ # class Object # implies < ::Object
+ # class SubObject < Object # this is _not_ ::Object
#
# Given <tt>class Container::Item</tt> RDoc assumes +Container+ is a module
- # unless it later sees <tt>class Container</tt>. add_class automatically
- # upgrades +name+ to a class in this case.
+ # unless it later sees <tt>class Container</tt>. +add_class+ automatically
+ # upgrades +given_name+ to a class in this case.
+
+ def add_class class_type, given_name, superclass = '::Object'
+ # superclass +nil+ is passed by the C parser in the following cases:
+ # - registering Object in 1.8 (correct)
+ # - registering BasicObject in 1.9 (correct)
+ # - registering RubyVM in 1.9 in iseq.c (incorrect: < Object in vm.c)
+ #
+ # If we later find a superclass for a registered class with a nil
+ # superclass, we must honor it.
+
+ # find the name & enclosing context
+ if given_name =~ /^:+(\w+)$/ then
+ full_name = $1
+ enclosing = top_level
+ name = full_name.split(/:+/).last
+ else
+ full_name = child_name given_name
+
+ if full_name =~ /^(.+)::(\w+)$/ then
+ name = $2
+ ename = $1
+ enclosing = RDoc::TopLevel.classes_hash[ename] ||
+ RDoc::TopLevel.modules_hash[ename]
+ # HACK: crashes in actionpack/lib/action_view/helpers/form_helper.rb (metaprogramming)
+ unless enclosing then
+ # try the given name at top level (will work for the above example)
+ enclosing = RDoc::TopLevel.classes_hash[given_name] || RDoc::TopLevel.modules_hash[given_name]
+ return enclosing if enclosing
+ # not found: create the parent(s)
+ names = ename.split('::')
+ enclosing = self
+ names.each do |n|
+ enclosing = enclosing.classes_hash[n] ||
+ enclosing.modules_hash[n] ||
+ enclosing.add_module(RDoc::NormalModule, n)
+ end
+ end
+ else
+ name = full_name
+ enclosing = self
+ end
+ end
+
+ # find the superclass full name
+ if superclass then
+ if superclass =~ /^:+/ then
+ superclass = $' #'
+ else
+ if superclass =~ /^(\w+):+(.+)$/ then
+ suffix = $2
+ mod = find_module_named($1)
+ superclass = mod.full_name + '::' + suffix if mod
+ else
+ mod = find_module_named(superclass)
+ superclass = mod.full_name if mod
+ end
+ end
- def add_class(class_type, name, superclass = 'Object')
- klass = add_class_or_module @classes, class_type, name, superclass
+ # did we believe it was a module?
+ mod = RDoc::TopLevel.modules_hash.delete superclass
- existing = klass.superclass
- existing = existing.name if existing and not String === existing
+ upgrade_to_class mod, RDoc::NormalClass, mod.parent if mod
- if superclass != existing and superclass != 'Object' then
- klass.superclass = superclass
+ # e.g., Object < Object
+ superclass = nil if superclass == full_name
end
- # If the parser encounters Container::Item before encountering
- # Container, then it assumes that Container is a module. This may not
- # be the case, so remove Container from the module list if present and
- # transfer any contained classes and modules to the new class.
+ klass = RDoc::TopLevel.classes_hash[full_name]
+
+ if klass then
+ # if TopLevel, it may not be registered in the classes:
+ enclosing.classes_hash[name] = klass
+ # update the superclass if needed
+ if superclass then
+ existing = klass.superclass
+ existing = existing.full_name unless existing.is_a?(String) if existing
+ if existing.nil? ||
+ (existing == 'Object' && superclass != 'Object') then
+ klass.superclass = superclass
+ end
+ end
+ else
+ # this is a new class
+ mod = RDoc::TopLevel.modules_hash.delete full_name
- mod = RDoc::TopLevel.modules_hash.delete klass.full_name
+ if mod then
+ klass = upgrade_to_class mod, RDoc::NormalClass, enclosing
- if mod then
- klass.classes_hash.update mod.classes_hash
- klass.modules_hash.update mod.modules_hash
- klass.method_list.concat mod.method_list
+ klass.superclass = superclass unless superclass.nil?
+ else
+ klass = class_type.new name, superclass
- @modules.delete klass.name
+ enclosing.add_class_or_module(klass, enclosing.classes_hash,
+ RDoc::TopLevel.classes_hash)
+ end
end
- RDoc::TopLevel.classes_hash[klass.full_name] = klass
-
klass
end
##
- # Instantiates a +class_type+ named +name+ and adds it the modules or
- # classes Hash +collection+.
-
- def add_class_or_module(collection, class_type, name, superclass = nil)
- full_name = child_name name
-
- mod = collection[name]
-
- if mod then
- mod.superclass = superclass unless mod.module?
- else
- all = if class_type == RDoc::NormalModule then
- RDoc::TopLevel.modules_hash
- else
- RDoc::TopLevel.classes_hash
- end
-
- mod = all[full_name]
-
- unless mod then
- mod = class_type.new name, superclass
- else
- # If the class has been encountered already, check that its
- # superclass has been set (it may not have been, depending on the
- # context in which it was encountered).
- if class_type == RDoc::NormalClass then
- mod.superclass = superclass unless mod.superclass
- end
- end
+ # Adds the class or module +mod+ to the modules or
+ # classes Hash +self_hash+, and to +all_hash+ (either
+ # <tt>TopLevel::modules_hash</tt> or <tt>TopLevel::classes_hash</tt>),
+ # unless #done_documenting is +true+. Sets the #parent of +mod+
+ # to +self+, and its #section to #current_section. Returns +mod+.
- unless @done_documenting then
- all[full_name] = mod
- collection[name] = mod
- end
+ def add_class_or_module mod, self_hash, all_hash
+ mod.section = @current_section # TODO declaring context? something is
+ # wrong here...
+ mod.parent = self
- mod.section = @current_section
- mod.parent = self
+ unless @done_documenting then
+ self_hash[mod.name] = mod
+ # this must be done AFTER adding mod to its parent, so that the full
+ # name is correct:
+ all_hash[mod.full_name] = mod
end
mod
end
##
- # Adds +constant+
+ # Adds +constant+ if not already there. If it is, updates the comment,
+ # value and/or is_alias_for of the known constant if they were empty/nil.
def add_constant(constant)
- add_to @constants, constant
+ return constant unless @document_self
+
+ # HACK: avoid duplicate 'PI' & 'E' in math.c (1.8.7 source code)
+ # (this is a #ifdef: should be handled by the C parser)
+ known = @constants_hash[constant.name]
+ if known
+ #$stderr.puts "\nconstant #{constant.name} already registered"
+ known.comment = constant.comment if known.comment.empty?
+ known.value = constant.value if known.value.nil? or known.value.strip.empty?
+ known.is_alias_for ||= constant.is_alias_for
+ else
+ @constants_hash[constant.name] = constant
+ add_to @constants, constant
+ end
end
##
- # Adds included module +include+
+ # Adds included module +include+ which should be an RDoc::Include
def add_include(include)
add_to @includes, include
end
##
- # Adds +method+
+ # Adds +method+ if not already there. If it is (as method or attribute),
+ # updates the comment if it was empty.
def add_method(method)
- method.visibility = @visibility
- add_to @method_list, method
-
- unmatched_alias_list = @unmatched_alias_lists[method.name]
- if unmatched_alias_list then
- unmatched_alias_list.each do |unmatched_alias|
- add_alias_impl unmatched_alias, method
- @aliases.delete unmatched_alias
- end
-
- @unmatched_alias_lists.delete method.name
+ return method unless @document_self
+
+ # HACK: avoid duplicate 'new' in io.c & struct.c (1.8.7 source code)
+ key = method.pretty_name
+ known = @methods_hash[key]
+ if known
+ # TODO issue stderr messages if --verbose
+ #$stderr.puts "\n#{display(method)} already registered as #{display(known)}"
+ known.comment = method.comment if known.comment.empty?
+ else
+ @methods_hash[key] = method
+ method.visibility = @visibility
+ add_to @method_list, method
+ resolve_aliases method
end
end
##
# Adds a module named +name+. If RDoc already knows +name+ is a class then
- # that class is returned instead. See also #add_class
+ # that class is returned instead. See also #add_class.
def add_module(class_type, name)
- return @classes[name] if @classes.key? name
+ mod = @classes[name] || @modules[name]
+ return mod if mod
+
+ full_name = child_name name
+ mod = RDoc::TopLevel.modules_hash[full_name] || class_type.new(name)
- add_class_or_module @modules, class_type, name, nil
+ add_class_or_module(mod, @modules, RDoc::TopLevel.modules_hash)
end
##
- # Adds an alias from +from+ to +name+
+ # Adds an alias from +from+ (a class or module) to +name+.
def add_module_alias from, name
- to_name = child_name name
+ return from if @done_documenting
- unless @done_documenting then
- if from.module? then
- RDoc::TopLevel.modules_hash
- else
- RDoc::TopLevel.classes_hash
- end[to_name] = from
+ to_name = child_name(name)
- if from.module? then
- @modules
- else
- @classes
- end[name] = from
+ # if we already know this name, don't register an alias:
+ # see the metaprogramming in lib/active_support/basic_object.rb,
+ # where we already know BasicObject as a class when we find
+ # BasicObject = BlankSlate
+ return from if RDoc::TopLevel.find_class_or_module(to_name)
+
+ if from.module? then
+ RDoc::TopLevel.modules_hash[to_name] = from
+ @modules[name] = from
+ else
+ RDoc::TopLevel.classes_hash[to_name] = from
+ @classes[name] = from
end
+ # HACK: register a constant for this alias:
+ # constant value and comment will be updated after,
+ # when the Ruby parser adds the constant
+ const = RDoc::Constant.new(name, nil, '')
+ const.is_alias_for = from
+ add_constant const
+
from
end
@@ -413,6 +530,8 @@ class RDoc::Context < RDoc::CodeObject
# Adds +require+ to this context's top level
def add_require(require)
+ return require unless @document_self
+
if RDoc::TopLevel === self then
add_to @requires, require
else
@@ -424,16 +543,37 @@ class RDoc::Context < RDoc::CodeObject
# Adds +thing+ to the collection +array+
def add_to(array, thing)
- array << thing if @document_self and not @done_documenting
+ array << thing if @document_self
thing.parent = self
thing.section = @current_section
end
##
+ # Is there any content?
+ # This means any of: comment, aliases, methods, attributes,
+ # external aliases, require, constant.
+ # Includes are also checked unless <tt>includes == false</tt>.
+
+ def any_content(includes = true)
+ @any_content ||= !(
+ @comment.empty? &&
+ @method_list.empty? &&
+ @attributes.empty? &&
+ @aliases.empty? &&
+ @external_aliases.empty? &&
+ @requires.empty? &&
+ @constants.empty?
+ )
+ @any_content || (includes && !@includes.empty?)
+ end
+
+ ##
# Creates the full name for a child with +name+
def child_name name
- if RDoc::TopLevel === self then
+ if name =~ /^:+/
+ $' #'
+ elsif RDoc::TopLevel === self then
name
else
"#{self.full_name}::#{name}"
@@ -441,6 +581,20 @@ class RDoc::Context < RDoc::CodeObject
end
##
+ # Class attributes
+
+ def class_attributes
+ @class_attributes ||= attributes.select { |a| a.singleton }
+ end
+
+ ##
+ # Class methods
+
+ def class_method_list
+ @class_method_list ||= method_list.select { |a| a.singleton }
+ end
+
+ ##
# Array of classes in this context
def classes
@@ -468,6 +622,14 @@ class RDoc::Context < RDoc::CodeObject
@in_files.include?(file)
end
+ def display(method_attr) # :nodoc:
+ if method_attr.is_a? RDoc::Attr
+ "#{method_attr.definition} #{method_attr.pretty_name}"
+ else
+ "method #{method_attr.pretty_name}"
+ end
+ end
+
##
# Iterator for attributes
@@ -504,10 +666,25 @@ class RDoc::Context < RDoc::CodeObject
end
##
+ # Finds an attribute +name+ with singleton value +singleton+.
+
+ def find_attribute(name, singleton)
+ name = $1 if name =~ /^(.*)=$/
+ @attributes.find { |a| a.name == name && a.singleton == singleton }
+ end
+
+ ##
# Finds an attribute with +name+ in this context
def find_attribute_named(name)
- @attributes.find { |m| m.name == name }
+ case name
+ when /\A#/ then
+ find_attribute name[1..-1], false
+ when /\A::/ then
+ find_attribute name[2..-1], true
+ else
+ @attributes.find { |a| a.name == name }
+ end
end
##
@@ -532,6 +709,27 @@ class RDoc::Context < RDoc::CodeObject
end
##
+ # Finds an external alias +name+ with singleton value +singleton+.
+
+ def find_external_alias(name, singleton)
+ @external_aliases.find { |m| m.name == name && m.singleton == singleton }
+ end
+
+ ##
+ # Finds an external alias with +name+ in this context
+
+ def find_external_alias_named(name)
+ case name
+ when /\A#/ then
+ find_external_alias name[1..-1], false
+ when /\A::/ then
+ find_external_alias name[2..-1], true
+ else
+ @external_aliases.find { |a| a.name == name }
+ end
+ end
+
+ ##
# Finds a file with +name+ in this context
def find_file_named(name)
@@ -546,26 +744,34 @@ class RDoc::Context < RDoc::CodeObject
end
##
- # Finds a method, constant, attribute, module or files named +symbol+ in
- # this context
+ # Finds a method, constant, attribute, external alias, module or file
+ # named +symbol+ in this context.
def find_local_symbol(symbol)
find_method_named(symbol) or
find_constant_named(symbol) or
find_attribute_named(symbol) or
+ find_external_alias_named(symbol) or
find_module_named(symbol) or
find_file_named(symbol)
end
##
+ # Finds a method named +name+ with singleton value +singleton+.
+
+ def find_method(name, singleton)
+ @method_list.find { |m| m.name == name && m.singleton == singleton }
+ end
+
+ ##
# Finds a instance or module method with +name+ in this context
def find_method_named(name)
case name
when /\A#/ then
- find_instance_method_named name[1..-1]
+ find_method name[1..-1], false
when /\A::/ then
- find_class_method_named name[2..-1]
+ find_method name[2..-1], true
else
@method_list.find { |meth| meth.name == name }
end
@@ -582,51 +788,42 @@ class RDoc::Context < RDoc::CodeObject
end
##
- # Look up +symbol+. If +method+ is non-nil, then we assume the symbol
- # references a module that contains that method.
+ # Look up +symbol+, first as a module, then as a local symbol.
+
+ def find_symbol(symbol)
+ find_symbol_module(symbol) || find_local_symbol(symbol)
+ end
+
+ ##
+ # Look up a module named +symbol+.
- def find_symbol(symbol, method = nil)
+ def find_symbol_module(symbol)
result = nil
+ # look for a class or module 'symbol'
case symbol
- when /^::([A-Z].*)/ then
- result = top_level.find_symbol($1)
- when /::/ then
- modules = symbol.split(/::/)
-
- unless modules.empty? then
- module_name = modules.shift
- result = find_module_named(module_name)
-
- if result then
- modules.each do |name|
- result = result.find_module_named name
- break unless result
- end
- end
+ when /^::/ then
+ result = RDoc::TopLevel.find_class_or_module(symbol)
+ when /^(\w+):+(.+)$/
+ suffix = $2
+ top = $1
+ searched = self
+ loop do
+ mod = searched.find_module_named(top)
+ break unless mod
+ result = RDoc::TopLevel.find_class_or_module(mod.full_name + '::' + suffix)
+ break if result || searched.is_a?(RDoc::TopLevel)
+ searched = searched.parent
end
- end
-
- unless result then
- # if a method is specified, then we're definitely looking for
- # a module, otherwise it could be any symbol
- if method then
- result = find_module_named symbol
- else
- result = find_local_symbol symbol
- if result.nil? then
- if symbol =~ /^[A-Z]/ then
- result = parent
- while result && result.name != symbol do
- result = result.parent
- end
- end
- end
+ else
+ searched = self
+ loop do
+ result = searched.find_module_named(symbol)
+ break if result || searched.is_a?(RDoc::TopLevel)
+ searched = searched.parent
end
end
- result = result.find_local_symbol method if result and method
-
result
end
@@ -638,10 +835,22 @@ class RDoc::Context < RDoc::CodeObject
end
##
+ # Does this context and its methods and constants all have documentation?
+ #
+ # (Yes, fully documented doesn't mean everything.)
+
+ def fully_documented?
+ documented? and
+ attributes.all? { |a| a.documented? } and
+ method_list.all? { |m| m.documented? } and
+ constants.all? { |c| c.documented? }
+ end
+
+ ##
# URL for this with a +prefix+
def http_url(prefix)
- path = full_name
+ path = name_for_path
path = path.gsub(/<<\s*(\w*)/, 'from-\1') if path =~ /<</
path = [prefix] + path.split('::')
@@ -649,15 +858,29 @@ class RDoc::Context < RDoc::CodeObject
end
##
+ # Instance attributes
+
+ def instance_attributes
+ @instance_attributes ||= attributes.reject { |a| a.singleton }
+ end
+
+ ##
+ # Instance methods
+
+ def instance_method_list
+ @instance_method_list ||= method_list.reject { |a| a.singleton }
+ end
+
+ ##
# Breaks method_list into a nested hash by type (class or instance) and
- # visibility (public, protected private)
+ # visibility (public, protected, private)
def methods_by_type
methods = {}
TYPES.each do |type|
visibilities = {}
- VISIBILITIES.each do |vis|
+ RDoc::VISIBILITIES.each do |vis|
visibilities[vis] = []
end
@@ -672,23 +895,11 @@ class RDoc::Context < RDoc::CodeObject
end
##
- # Yields Method and Attr entries matching the list of names in +methods+.
- # Attributes are only returned when +singleton+ is false.
+ # Yields AnyMethod and Attr entries matching the list of names in +methods+.
def methods_matching(methods, singleton = false)
- count = 0
-
- @method_list.each do |m|
- if methods.include? m.name and m.singleton == singleton then
- yield m
- count += 1
- end
- end
-
- return if count == methods.size || singleton
-
- @attributes.each do |a|
- yield a if methods.include? a.name
+ (@method_list + @attributes).each do |m|
+ yield m if methods.include?(m.name) and m.singleton == singleton
end
end
@@ -707,6 +918,14 @@ class RDoc::Context < RDoc::CodeObject
end
##
+ # Name to use to generate the url.
+ # <tt>#full_name</tt> by default.
+
+ def name_for_path
+ full_name
+ end
+
+ ##
# Changes the visibility for new methods to +visibility+
def ongoing_visibility=(visibility)
@@ -714,35 +933,63 @@ class RDoc::Context < RDoc::CodeObject
end
##
- # Record which file +top_level+ is in
+ # Record +top_level+ as a file +self+ is in.
def record_location(top_level)
@in_files << top_level unless @in_files.include?(top_level)
end
##
- # If a class's documentation is turned off after we've started collecting
- # methods etc., we need to remove the ones we have
-
- def remove_methods_etc
- initialize_methods_etc
+ # Should we remove this context from the documentation?
+ #
+ # The answer is yes if:
+ # * #received_nodoc is +true+
+ # * #any_content is +false+ (not counting includes)
+ # * All #includes are modules (not a string), and their module has
+ # <tt>#remove_from_documentation? == true</tt>
+ # * All classes and modules have <tt>#remove_from_documentation? == true</tt>
+
+ def remove_from_documentation?
+ @remove_from_documentation ||=
+ @received_nodoc &&
+ !any_content(false) &&
+ @includes.all? { |i| !i.module.is_a?(String) && i.module.remove_from_documentation? } &&
+ classes_and_modules.all? { |cm| cm.remove_from_documentation? }
end
##
- # Given an array +methods+ of method names, set the visibility of each to
- # +visibility+
+ # Removes methods and attributes with a visibility less than +min_visibility+.
+ #--
+ # TODO mark the visibility of attributes in the template (if not public?)
- def set_visibility_for(methods, visibility, singleton = false)
- methods_matching methods, singleton do |m|
- m.visibility = visibility
+ def remove_invisible(min_visibility)
+ return if min_visibility == :private
+ remove_invisible_in @method_list, min_visibility
+ remove_invisible_in @attributes, min_visibility
+ end
+
+ def remove_invisible_in(array, min_visibility) # :nodoc:
+ if min_visibility == :public
+ array.reject! { |e| e.visibility != :public }
+ else
+ array.reject! { |e| e.visibility == :private }
end
end
##
- # Removes classes and modules when we see a :nodoc: all
+ # Tries to resolve unmatched aliases when a method
+ # or attribute has just been added.
- def remove_classes_and_modules
- initialize_classes_and_modules
+ def resolve_aliases(added)
+ # resolve any pending unmatched aliases
+ key = added.pretty_name
+ unmatched_alias_list = @unmatched_alias_lists[key]
+ return unless unmatched_alias_list
+ unmatched_alias_list.each do |unmatched_alias|
+ added.add_alias unmatched_alias, self
+ @external_aliases.delete unmatched_alias
+ end
+ @unmatched_alias_lists.delete key
end
##
@@ -754,7 +1001,24 @@ class RDoc::Context < RDoc::CodeObject
end
##
+ # Given an array +methods+ of method names, set the visibility of each to
+ # +visibility+
+
+ def set_visibility_for(methods, visibility, singleton = false)
+ methods_matching methods, singleton do |m|
+ m.visibility = visibility
+ end
+ end
+
+ def to_s # :nodoc:
+ "#{self.class.name} #{self.full_name}"
+ end
+
+ ##
# Return the TopLevel that owns us
+ #--
+ # FIXME we can be 'owned' by several TopLevel (see #record_location &
+ # #in_files)
def top_level
return @top_level if defined? @top_level
@@ -763,5 +1027,20 @@ class RDoc::Context < RDoc::CodeObject
@top_level
end
+ ##
+ # Upgrades NormalModule +mod+ in +enclosing+ to a +class_type+
+
+ def upgrade_to_class mod, class_type, enclosing
+ enclosing.modules_hash.delete mod.name
+
+ klass = RDoc::ClassModule.from_module class_type, mod
+
+ # if it was there, then we keep it even if done_documenting
+ RDoc::TopLevel.classes_hash[mod.full_name] = klass
+ enclosing.classes_hash[mod.name] = klass
+
+ klass
+ end
+
end