diff options
author | drbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-11-27 04:28:14 +0000 |
---|---|---|
committer | drbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-11-27 04:28:14 +0000 |
commit | 1c279a7d2753949c725754e1302f791b76358114 (patch) | |
tree | 36aa3bdde250e564445eba5f2e25fcb96bcb6cef /lib/rdoc/context.rb | |
parent | c72f0daa877808e4fa5018b3191ca09d4b97c03d (diff) | |
download | ruby-1c279a7d2753949c725754e1302f791b76358114.tar.gz |
* lib/rdoc*: Updated to RDoc 4.0 (pre-release)
* bin/rdoc: ditto
* test/rdoc: ditto
* NEWS: Updated with RDoc 4.0 information
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37889 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/rdoc/context.rb')
-rw-r--r-- | lib/rdoc/context.rb | 323 |
1 files changed, 160 insertions, 163 deletions
diff --git a/lib/rdoc/context.rb b/lib/rdoc/context.rb index abdab2026d..6f9deae4a8 100644 --- a/lib/rdoc/context.rb +++ b/lib/rdoc/context.rb @@ -1,4 +1,4 @@ -require 'rdoc/code_object' +require 'cgi' ## # A Context is something that can hold modules, classes, methods, attributes, @@ -15,6 +15,12 @@ class RDoc::Context < RDoc::CodeObject TYPES = %w[class instance] ## + # If a context has these titles it will be sorted in this order. + + TOMDOC_TITLES = [nil, 'Public', 'Internal', 'Deprecated'] # :nodoc: + TOMDOC_TITLES_SORT = TOMDOC_TITLES.sort_by { |title| title.to_s } # :nodoc: + + ## # Class/module aliases attr_reader :aliases @@ -25,6 +31,11 @@ class RDoc::Context < RDoc::CodeObject attr_reader :attributes ## + # Block params to be used in the next MethodAttr parsed under this context + + attr_accessor :block_params + + ## # Constants defined attr_reader :constants @@ -45,6 +56,11 @@ class RDoc::Context < RDoc::CodeObject attr_reader :includes ## + # Modules this context is extended with + + attr_reader :extends + + ## # Methods defined in this context attr_reader :method_list @@ -72,7 +88,7 @@ class RDoc::Context < RDoc::CodeObject attr_accessor :unmatched_alias_lists ## - # Aliases that could not eventually be resolved. + # Aliases that could not be resolved. attr_reader :external_aliases @@ -88,121 +104,14 @@ class RDoc::Context < RDoc::CodeObject attr_reader :methods_hash ## - # Hash of registered constants. + # Params to be used in the next MethodAttr parsed under this context - attr_reader :constants_hash + attr_accessor :params ## - # A section of documentation like: - # - # # :section: The title - # # The body - # - # Sections can be referenced multiple times and will be collapsed into a - # single section. - - class Section - - include RDoc::Text - - ## - # Section comment - - attr_reader :comment - - ## - # Context this Section lives in - - attr_reader :parent - - ## - # Section title - - attr_reader :title - - @@sequence = "SEC00000" - - ## - # Creates a new section with +title+ and +comment+ - - def initialize parent, title, comment - @parent = parent - @title = title ? title.strip : title - - @@sequence.succ! - @sequence = @@sequence.dup - - @comment = extract_comment comment - end - - ## - # Sections are equal when they have the same #title - - def == other - self.class === other and @title == other.title - end - - ## - # Anchor reference for linking to this section - - def aref - title = @title || '[untitled]' - - CGI.escape(title).gsub('%', '-').sub(/^-/, '') - end - - ## - # Appends +comment+ to the current comment separated by a rule. - - def comment= comment - comment = extract_comment comment - - return if comment.empty? - - if @comment then - @comment += "\n# ---\n#{comment}" - else - @comment = comment - end - end - - ## - # Extracts 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 - # - # # :section: The title - # # The body - - def extract_comment comment - if comment =~ /^#[ \t]*:section:.*\n/ then - start = $` - rest = $' - - if start.empty? then - rest - else - rest.sub(/#{start.chomp}\Z/, '') - end - else - comment - end - end - - def inspect # :nodoc: - "#<%s:0x%x %p>" % [self.class, object_id, title] - end - - ## - # Section sequence number (deprecated) - - def sequence - warn "RDoc::Context::Section#sequence is deprecated, use #aref" - @sequence - end + # Hash of registered constants. - end + attr_reader :constants_hash ## # Creates an unnamed empty context with public current visibility @@ -235,6 +144,7 @@ class RDoc::Context < RDoc::CodeObject @aliases = [] @requires = [] @includes = [] + @extends = [] @constants = [] @external_aliases = [] @@ -242,8 +152,12 @@ class RDoc::Context < RDoc::CodeObject # a method not yet encountered). @unmatched_alias_lists = {} - @methods_hash = {} + @methods_hash = {} @constants_hash = {} + + @params = nil + + @store ||= nil end ## @@ -366,12 +280,12 @@ class RDoc::Context < RDoc::CodeObject if full_name =~ /^(.+)::(\w+)$/ then name = $2 ename = $1 - enclosing = RDoc::TopLevel.classes_hash[ename] || - RDoc::TopLevel.modules_hash[ename] + enclosing = @store.classes_hash[ename] || @store.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] + enclosing = @store.classes_hash[given_name] || + @store.modules_hash[given_name] return enclosing if enclosing # not found: create the parent(s) names = ename.split('::') @@ -410,7 +324,7 @@ class RDoc::Context < RDoc::CodeObject end # did we believe it was a module? - mod = RDoc::TopLevel.modules_hash.delete superclass + mod = @store.modules_hash.delete superclass upgrade_to_class mod, RDoc::NormalClass, mod.parent if mod @@ -418,7 +332,7 @@ class RDoc::Context < RDoc::CodeObject superclass = nil if superclass == full_name end - klass = RDoc::TopLevel.classes_hash[full_name] + klass = @store.classes_hash[full_name] if klass then # if TopLevel, it may not be registered in the classes: @@ -435,7 +349,7 @@ class RDoc::Context < RDoc::CodeObject end else # this is a new class - mod = RDoc::TopLevel.modules_hash.delete full_name + mod = @store.modules_hash.delete full_name if mod then klass = upgrade_to_class mod, RDoc::NormalClass, enclosing @@ -445,10 +359,12 @@ class RDoc::Context < RDoc::CodeObject klass = class_type.new name, superclass enclosing.add_class_or_module(klass, enclosing.classes_hash, - RDoc::TopLevel.classes_hash) + @store.classes_hash) end end + klass.parent = self + klass end @@ -463,6 +379,7 @@ class RDoc::Context < RDoc::CodeObject mod.section = current_section # TODO declaring context? something is # wrong here... mod.parent = self + mod.store = @store unless @done_documenting then self_hash[mod.name] = mod @@ -504,13 +421,21 @@ class RDoc::Context < RDoc::CodeObject # Adds included module +include+ which should be an RDoc::Include def add_include include - add_to @includes, include unless - @includes.map { |i| i.full_name }.include? include.full_name + add_to @includes, include include end ## + # Adds extension module +ext+ which should be an RDoc::Extend + + def add_extend ext + add_to @extends, ext + + ext + end + + ## # Adds +method+ if not already there. If it is (as method or attribute), # updates the comment if it was empty. @@ -523,6 +448,10 @@ class RDoc::Context < RDoc::CodeObject if known then known.comment = method.comment if known.comment.empty? + previously = ", previously in #{known.file}" unless + method.file == known.file + @store.rdoc.options.warn \ + "Duplicate method #{known.full_name} in #{method.file}#{previously}" else @methods_hash[key] = method method.visibility = @visibility @@ -542,9 +471,9 @@ class RDoc::Context < RDoc::CodeObject return mod if mod full_name = child_name name - mod = RDoc::TopLevel.modules_hash[full_name] || class_type.new(name) + mod = @store.modules_hash[full_name] || class_type.new(name) - add_class_or_module(mod, @modules, RDoc::TopLevel.modules_hash) + add_class_or_module mod, @modules, @store.modules_hash end ## @@ -554,31 +483,34 @@ class RDoc::Context < RDoc::CodeObject def add_module_alias from, name, file return from if @done_documenting - to_name = child_name(name) + to_name = child_name name # 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 + # where we already know BasicObject is a class when we find # BasicObject = BlankSlate - return from if RDoc::TopLevel.find_class_or_module(to_name) + return from if @store.find_class_or_module to_name - if from.module? then - RDoc::TopLevel.modules_hash[to_name] = from - @modules[name] = from + to = from.dup + to.name = name + to.full_name = nil + + if to.module? then + @store.modules_hash[to_name] = to + @modules[name] = to else - RDoc::TopLevel.classes_hash[to_name] = from - @classes[name] = from + @store.classes_hash[to_name] = to + @classes[name] = to 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, '' + # Registers a constant for this alias. The constant value and comment + # will be updated later, when the Ruby parser adds the constant + const = RDoc::Constant.new name, nil, to.comment const.record_location file const.is_alias_for = from add_constant const - from + to end ## @@ -602,9 +534,9 @@ class RDoc::Context < RDoc::CodeObject # # See also RDoc::Context::Section - def add_section title, comment + def add_section title, comment = nil if section = @sections[title] then - section.comment = comment + section.add_comment comment if comment else section = Section.new self, title, comment @sections[title] = section @@ -616,9 +548,11 @@ class RDoc::Context < RDoc::CodeObject ## # Adds +thing+ to the collection +array+ - def add_to(array, thing) + def add_to array, thing array << thing if @document_self - thing.parent = self + + thing.parent = self + thing.store = @store if @store thing.section = current_section end @@ -628,7 +562,7 @@ class RDoc::Context < RDoc::CodeObject # This means any of: comment, aliases, methods, attributes, external # aliases, require, constant. # - # Includes are also checked unless <tt>includes == false</tt>. + # Includes and extends are also checked unless <tt>includes == false</tt>. def any_content(includes = true) @any_content ||= !( @@ -640,7 +574,7 @@ class RDoc::Context < RDoc::CodeObject @requires.empty? && @constants.empty? ) - @any_content || (includes && !@includes.empty?) + @any_content || (includes && !(@includes + @extends).empty? ) end ## @@ -723,6 +657,9 @@ class RDoc::Context < RDoc::CodeObject ## # Iterator for ancestors for duck-typing. Does nothing. See # RDoc::ClassModule#each_ancestor. + # + # This method exists to make it easy to work with Context subclasses that + # aren't part of RDoc. def each_ancestor # :nodoc: end @@ -756,10 +693,19 @@ class RDoc::Context < RDoc::CodeObject end ## + # Iterator for extension modules + + def each_extend # :yields: extend + @extends.each do |e| yield e end + end + + ## # Iterator for methods def each_method # :yields: method - @method_list.sort.each {|m| yield m} + return enum_for __method__ unless block_given? + + @method_list.sort.each { |m| yield m } end ## @@ -773,13 +719,15 @@ class RDoc::Context < RDoc::CodeObject # NOTE: Do not edit collections yielded by this method def each_section # :yields: section, constants, attributes - constants = @constants.group_by do |constant| constant.section end - constants.default = [] + return enum_for __method__ unless block_given? + constants = @constants.group_by do |constant| constant.section end attributes = @attributes.group_by do |attribute| attribute.section end + + constants.default = [] attributes.default = [] - @sections.sort_by { |title, _| title.to_s }.each do |_, section| + sort_sections.each do |section| yield section, constants[section].sort, attributes[section].sort end end @@ -851,8 +799,8 @@ class RDoc::Context < RDoc::CodeObject ## # Finds a file with +name+ in this context - def find_file_named(name) - top_level.class.find_file_named(name) + def find_file_named name + @store.find_file_named name end ## @@ -922,21 +870,21 @@ class RDoc::Context < RDoc::CodeObject # look for a class or module 'symbol' case symbol when /^::/ then - result = RDoc::TopLevel.find_class_or_module(symbol) + result = @store.find_class_or_module symbol when /^(\w+):+(.+)$/ suffix = $2 top = $1 searched = self - loop do + while searched do mod = searched.find_module_named(top) break unless mod - result = RDoc::TopLevel.find_class_or_module(mod.full_name + '::' + suffix) + result = @store.find_class_or_module "#{mod.full_name}::#{suffix}" break if result || searched.is_a?(RDoc::TopLevel) searched = searched.parent end else searched = self - loop do + while searched do result = searched.find_module_named(symbol) break if result || searched.is_a?(RDoc::TopLevel) searched = searched.parent @@ -985,6 +933,8 @@ class RDoc::Context < RDoc::CodeObject ## # Instance methods + #-- + # TODO rename to instance_methods def instance_method_list @instance_method_list ||= method_list.reject { |a| a.singleton } @@ -1098,24 +1048,23 @@ class RDoc::Context < RDoc::CodeObject ## # Only called when min_visibility == :public or :private - def remove_invisible_in(array, min_visibility) # :nodoc: - if min_visibility == :public + def remove_invisible_in array, min_visibility # :nodoc: + if min_visibility == :public then array.reject! { |e| e.visibility != :public and not e.force_documentation } else array.reject! { |e| - e.visibility == :private and - not e.force_documentation + e.visibility == :private and not e.force_documentation } end end ## - # Tries to resolve unmatched aliases when a method - # or attribute has just been added. + # Tries to resolve unmatched aliases when a method or attribute has just + # been added. - def resolve_aliases(added) + def resolve_aliases added # resolve any pending unmatched aliases key = added.pretty_name unmatched_alias_list = @unmatched_alias_lists[key] @@ -1128,6 +1077,31 @@ class RDoc::Context < RDoc::CodeObject end ## + # Returns RDoc::Context::Section objects referenced in this context for use + # in a table of contents. + + def section_contents + used_sections = {} + + each_method do |method| + next unless method.display? + + used_sections[method.section] = true + end + + # order found sections + sections = sort_sections.select do |section| + used_sections[section] + end + + # only the default section is used + return [] if + sections.length == 1 and not sections.first.title + + sections + end + + ## # Sections in this context def sections @@ -1155,6 +1129,26 @@ class RDoc::Context < RDoc::CodeObject end end + ## + # Sorts sections alphabetically (default) or in TomDoc fashion (none, + # Public, Internal, Deprecated) + + def sort_sections + titles = @sections.map { |title, _| title } + + if titles.length > 1 and + TOMDOC_TITLES_SORT == + (titles | TOMDOC_TITLES).sort_by { |title| title.to_s } then + @sections.values_at(*TOMDOC_TITLES).compact + else + @sections.sort_by { |title, _| + title.to_s + }.map { |_, section| + section + } + end + end + def to_s # :nodoc: "#{self.class.name} #{self.full_name}" end @@ -1179,13 +1173,16 @@ class RDoc::Context < RDoc::CodeObject enclosing.modules_hash.delete mod.name klass = RDoc::ClassModule.from_module class_type, mod + klass.store = @store # 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 + @store.classes_hash[mod.full_name] = klass + enclosing.classes_hash[mod.name] = klass klass end + autoload :Section, 'rdoc/context/section' + end |