diff options
Diffstat (limited to 'lib/rdoc/context.rb')
-rw-r--r-- | lib/rdoc/context.rb | 711 |
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 |