1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* 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
This commit is contained in:
drbrain 2012-11-27 04:28:14 +00:00
parent c72f0daa87
commit 1c279a7d27
233 changed files with 45019 additions and 5100 deletions

View file

@ -1,4 +1,4 @@
require 'rdoc/code_object'
require 'cgi'
##
# A Context is something that can hold modules, classes, methods, attributes,
@ -14,6 +14,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
@ -24,6 +30,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
@ -44,6 +55,11 @@ class RDoc::Context < RDoc::CodeObject
attr_reader :includes
##
# Modules this context is extended with
attr_reader :extends
##
# Methods defined in this context
@ -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
@ -87,123 +103,16 @@ class RDoc::Context < RDoc::CodeObject
attr_reader :methods_hash
##
# Params to be used in the next MethodAttr parsed under this context
attr_accessor :params
##
# Hash of registered constants.
attr_reader :constants_hash
##
# 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
end
##
# 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,12 +421,20 @@ 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
@ -755,11 +692,20 @@ class RDoc::Context < RDoc::CodeObject
@includes.each do |i| yield i end
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]
@ -1127,6 +1076,31 @@ class RDoc::Context < RDoc::CodeObject
@unmatched_alias_lists.delete key
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
@ -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