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:
parent
c72f0daa87
commit
1c279a7d27
233 changed files with 45019 additions and 5100 deletions
|
@ -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
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue