summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authordrbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2011-06-16 04:59:24 +0000
committerdrbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2011-06-16 04:59:24 +0000
commitb7528b5edb1f9148ea00ebb6151720e5943b3f0b (patch)
tree4caf55c53adb188170240f54b924892fbc5f9814 /lib
parent97ac172d58d695305c39d555155318edb99f1ea7 (diff)
* lib/rdoc.rb: Import RDoc 3.7 release candidate
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@32115 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib')
-rw-r--r--lib/rdoc.rb5
-rw-r--r--lib/rdoc/any_method.rb19
-rw-r--r--lib/rdoc/attr.rb17
-rw-r--r--lib/rdoc/class_module.rb198
-rw-r--r--lib/rdoc/code_object.rb9
-rw-r--r--lib/rdoc/context.rb104
-rw-r--r--lib/rdoc/generator/markup.rb4
-rw-r--r--lib/rdoc/generator/ri.rb5
-rw-r--r--lib/rdoc/generator/template/darkfish/rdoc.css4
-rw-r--r--lib/rdoc/known_classes.rb4
-rw-r--r--lib/rdoc/markup.rb68
-rw-r--r--lib/rdoc/markup/document.rb36
-rw-r--r--lib/rdoc/markup/formatter.rb16
-rw-r--r--lib/rdoc/markup/formatter_test_case.rb10
-rw-r--r--lib/rdoc/markup/indented_paragraph.rb33
-rw-r--r--lib/rdoc/markup/parser.rb1
-rw-r--r--lib/rdoc/markup/pre_process.rb7
-rw-r--r--lib/rdoc/markup/to_ansi.rb2
-rw-r--r--lib/rdoc/markup/to_bs.rb2
-rw-r--r--lib/rdoc/markup/to_html.rb4
-rw-r--r--lib/rdoc/markup/to_html_crossref.rb5
-rw-r--r--lib/rdoc/markup/to_rdoc.rb11
-rw-r--r--lib/rdoc/markup/to_test.rb2
-rw-r--r--lib/rdoc/markup/to_tt_only.rb2
-rw-r--r--lib/rdoc/parser/c.rb95
-rw-r--r--lib/rdoc/parser/ruby.rb26
-rw-r--r--lib/rdoc/rdoc.rb17
-rw-r--r--lib/rdoc/ri/driver.rb15
-rw-r--r--lib/rdoc/ri/store.rb137
-rw-r--r--lib/rdoc/rubygems_hook.rb220
-rw-r--r--lib/rdoc/text.rb2
-rw-r--r--lib/rdoc/top_level.rb31
32 files changed, 927 insertions, 184 deletions
diff --git a/lib/rdoc.rb b/lib/rdoc.rb
index aee6da5049..3aa15dfa52 100644
--- a/lib/rdoc.rb
+++ b/lib/rdoc.rb
@@ -27,7 +27,8 @@ $DEBUG_RDOC = nil
# * If you want to use RDoc to create documentation for your Ruby source files,
# see RDoc::Markup and refer to <tt>rdoc --help</tt> for command line
# usage.
-# * If you want to generate documentation for extensions written in C, see
+# * If you want to write documentation for Ruby files see RDoc::Parser::Ruby
+# * If you want to write documentation for extensions written in C see
# RDoc::Parser::C
# * If you want to generate documentation using <tt>rake</tt> see RDoc::Task.
# * If you want to drive RDoc programmatically, see RDoc::RDoc.
@@ -103,7 +104,7 @@ module RDoc
##
# RDoc version you are using
- VERSION = '3.6.1'
+ VERSION = '3.7'
##
# Method visibilities
diff --git a/lib/rdoc/any_method.rb b/lib/rdoc/any_method.rb
index f691598910..c008edfe95 100644
--- a/lib/rdoc/any_method.rb
+++ b/lib/rdoc/any_method.rb
@@ -6,7 +6,7 @@ require 'rdoc/token_stream'
class RDoc::AnyMethod < RDoc::MethodAttr
- MARSHAL_VERSION = 0 # :nodoc:
+ MARSHAL_VERSION = 1 # :nodoc:
##
# Don't rename \#initialize to \::new
@@ -44,7 +44,7 @@ class RDoc::AnyMethod < RDoc::MethodAttr
##
# Adds +an_alias+ as an alias for this method in +context+.
- def add_alias(an_alias, context = nil )
+ def add_alias an_alias, context = nil
method = self.class.new an_alias.text, an_alias.new_name
method.record_location an_alias.file
@@ -54,7 +54,7 @@ class RDoc::AnyMethod < RDoc::MethodAttr
method.comment = an_alias.comment
method.is_alias_for = self
@aliases << method
- context.add_method( method ) if context
+ context.add_method method if context
method
end
@@ -83,7 +83,7 @@ class RDoc::AnyMethod < RDoc::MethodAttr
def marshal_dump
aliases = @aliases.map do |a|
- [a.full_name, parse(a.comment)]
+ [a.name, parse(a.comment)]
end
[ MARSHAL_VERSION,
@@ -96,6 +96,7 @@ class RDoc::AnyMethod < RDoc::MethodAttr
@block_params,
aliases,
@params,
+ @file.absolute_name,
]
end
@@ -112,6 +113,7 @@ class RDoc::AnyMethod < RDoc::MethodAttr
@token_stream = nil
@aliases = []
+ version = array[0]
@name = array[1]
@full_name = array[2]
@singleton = array[3]
@@ -119,6 +121,11 @@ class RDoc::AnyMethod < RDoc::MethodAttr
@comment = array[5]
@call_seq = array[6]
@block_params = array[7]
+
+ array[8].each do |new_name, comment|
+ add_alias RDoc::Alias.new(nil, @name, new_name, comment, @singleton)
+ end
+
@params = array[9]
@parent_name = if @full_name =~ /#/ then
@@ -129,9 +136,7 @@ class RDoc::AnyMethod < RDoc::MethodAttr
name.join '::'
end
- array[8].each do |new_name, comment|
- add_alias RDoc::Alias.new(nil, @name, new_name, comment, @singleton)
- end
+ @file = RDoc::TopLevel.new array[10] if version > 0
end
##
diff --git a/lib/rdoc/attr.rb b/lib/rdoc/attr.rb
index f04fe168b1..5d9bc17831 100644
--- a/lib/rdoc/attr.rb
+++ b/lib/rdoc/attr.rb
@@ -6,7 +6,7 @@ require 'rdoc/method_attr'
class RDoc::Attr < RDoc::MethodAttr
- MARSHAL_VERSION = 1 # :nodoc:
+ MARSHAL_VERSION = 2 # :nodoc:
##
# Is the attribute readable ('R'), writable ('W') or both ('RW')?
@@ -92,6 +92,7 @@ class RDoc::Attr < RDoc::MethodAttr
@visibility,
parse(@comment),
singleton,
+ @file.absolute_name,
]
end
@@ -103,6 +104,7 @@ class RDoc::Attr < RDoc::MethodAttr
# * #parent_name
def marshal_load array
+ version = array[0]
@name = array[1]
@full_name = array[2]
@rw = array[3]
@@ -110,9 +112,22 @@ class RDoc::Attr < RDoc::MethodAttr
@comment = array[5]
@singleton = array[6] || false # MARSHAL_VERSION == 0
+ @file = RDoc::TopLevel.new array[7] if version > 1
+
@parent_name = @full_name
end
+ def pretty_print q # :nodoc:
+ q.group 2, "[#{self.class.name} #{full_name} #{rw} #{visibility}", "]" do
+ unless comment.empty? then
+ q.breakable
+ q.text "comment:"
+ q.breakable
+ q.pp @comment
+ end
+ end
+ end
+
def to_s # :nodoc:
"#{definition} #{name} in: #{parent}"
end
diff --git a/lib/rdoc/class_module.rb b/lib/rdoc/class_module.rb
index 89441b3e68..d7a14b73eb 100644
--- a/lib/rdoc/class_module.rb
+++ b/lib/rdoc/class_module.rb
@@ -6,13 +6,26 @@ require 'rdoc/context'
class RDoc::ClassModule < RDoc::Context
- MARSHAL_VERSION = 0 # :nodoc:
+ ##
+ # 1::
+ # RDoc 3.7
+ # * Added visibility, singleton and file to attributes
+ # * Added file to constants
+ # * Added file to includes
+ # * Added file to methods
+
+ MARSHAL_VERSION = 1 # :nodoc:
##
# Constants that are aliases for this class or module
attr_accessor :constant_aliases
+ ##
+ # Comment and the location it came from. Use #add_comment to add comments
+
+ attr_reader :comment_location
+
attr_accessor :diagram # :nodoc:
##
@@ -23,10 +36,16 @@ class RDoc::ClassModule < RDoc::Context
##
# Return a RDoc::ClassModule of class +class_type+ that is a copy
# of module +module+. Used to promote modules to classes.
+ #--
+ # TODO move to RDoc::NormalClass (I think)
+
+ def self.from_module class_type, mod
+ klass = class_type.new mod.name
+
+ mod.comment_location.each do |comment, location|
+ klass.add_comment comment, location
+ end
- def self.from_module(class_type, mod)
- klass = class_type.new(mod.name)
- klass.comment = mod.comment
klass.parent = mod.parent
klass.section = mod.section
klass.viewer = mod.viewer
@@ -85,10 +104,28 @@ class RDoc::ClassModule < RDoc::Context
@is_alias_for = nil
@name = name
@superclass = superclass
+ @comment_location = [] # [[comment, location]]
+
super()
end
##
+ # Adds +comment+ to this ClassModule's list of comments at +location+. This
+ # method is preferred over #comment= since it allows ri data to be updated
+ # across multiple runs.
+
+ def add_comment comment, location
+ return if comment.empty?
+
+ original = comment
+
+ comment = normalize_comment comment
+ @comment_location << [comment, location]
+
+ self.comment = original
+ end
+
+ ##
# Ancestors list for this ClassModule: the list of included modules
# (classes will add their superclass if any).
#
@@ -112,6 +149,8 @@ class RDoc::ClassModule < RDoc::Context
end
##
+ # This method is deprecated, use #add_comment instead.
+ #
# Appends +comment+ to the current comment, but separated by a rule. Works
# more like <tt>+=</tt>.
@@ -119,10 +158,9 @@ class RDoc::ClassModule < RDoc::Context
return if comment.empty?
comment = normalize_comment comment
- comment = "#{@comment}\n---\n#{comment}" unless
- @comment.empty?
+ comment = "#{@comment}\n---\n#{comment}" unless @comment.empty?
- super
+ super comment
end
##
@@ -185,15 +223,16 @@ class RDoc::ClassModule < RDoc::Context
end
def marshal_dump # :nodoc:
- # TODO must store the singleton attribute
attrs = attributes.sort.map do |attr|
- [attr.name, attr.rw]
+ [ attr.name, attr.rw,
+ attr.visibility, attr.singleton, attr.file_name,
+ ]
end
method_types = methods_by_type.map do |type, visibilities|
visibilities = visibilities.map do |visibility, methods|
method_names = methods.map do |method|
- method.name
+ [method.name, method.file_name]
end
[visibility, method_names.uniq]
@@ -206,51 +245,67 @@ class RDoc::ClassModule < RDoc::Context
@name,
full_name,
@superclass,
- parse(@comment),
+ parse(@comment_location),
attrs,
constants.map do |const|
- [const.name, parse(const.comment)]
+ [const.name, parse(const.comment), const.file_name]
end,
includes.map do |incl|
- [incl.name, parse(incl.comment)]
+ [incl.name, parse(incl.comment), incl.file_name]
end,
method_types,
]
end
def marshal_load array # :nodoc:
- # TODO must restore the singleton attribute
initialize_methods_etc
- @document_self = true
- @done_documenting = false
- @current_section = nil
- @parent = nil
- @visibility = nil
+ @current_section = nil
+ @document_self = true
+ @done_documenting = false
+ @parent = nil
+ @temporary_section = nil
+ @visibility = nil
@name = array[1]
@full_name = array[2]
@superclass = array[3]
@comment = array[4]
- array[5].each do |name, rw|
- add_attribute RDoc::Attr.new(nil, name, rw, nil)
+ @comment_location = if RDoc::Markup::Document === @comment.parts.first then
+ @comment
+ else
+ RDoc::Markup::Document.new @comment
+ end
+
+ array[5].each do |name, rw, visibility, singleton, file|
+ singleton ||= false
+ visibility ||= :public
+
+ attr = RDoc::Attr.new nil, name, rw, nil, singleton
+
+ add_attribute attr
+ attr.visibility = visibility
+ attr.record_location RDoc::TopLevel.new file
end
- array[6].each do |name, comment|
- add_constant RDoc::Constant.new(name, nil, comment)
+ array[6].each do |name, comment, file|
+ const = add_constant RDoc::Constant.new(name, nil, comment)
+ const.record_location RDoc::TopLevel.new file
end
- array[7].each do |name, comment|
- add_include RDoc::Include.new(name, comment)
+ array[7].each do |name, comment, file|
+ incl = add_include RDoc::Include.new(name, comment)
+ incl.record_location RDoc::TopLevel.new file
end
array[8].each do |type, visibilities|
visibilities.each do |visibility, methods|
@visibility = visibility
- methods.each do |name|
+ methods.each do |name, file|
method = RDoc::AnyMethod.new nil, name
method.singleton = true if type == 'class'
+ method.record_location RDoc::TopLevel.new file
add_method method
end
end
@@ -258,37 +313,73 @@ class RDoc::ClassModule < RDoc::Context
end
##
- # Merges +class_module+ into this ClassModule
+ # Merges +class_module+ into this ClassModule.
+ #
+ # The data in +class_module+ is preferred over the receiver.
def merge class_module
- comment = class_module.comment
+ other_document = parse class_module.comment_location
- if comment then
- document = parse @comment
+ if other_document then
+ document = parse @comment_location
- comment.parts.concat document.parts
+ document = document.merge other_document
- @comment = comment
+ @comment = @comment_location = document
end
- class_module.each_attribute do |attr|
- if match = attributes.find { |a| a.name == attr.name } then
- match.rw = [match.rw, attr.rw].compact.uniq.join
- else
+ merge_collections attributes, class_module.attributes do |add, attr|
+ if add then
add_attribute attr
+ else
+ @attributes.delete attr
+ @methods_hash.delete attr.pretty_name
end
end
- class_module.each_constant do |const|
- add_constant const
+ merge_collections constants, class_module.constants do |add, const|
+ if add then
+ add_constant const
+ else
+ @constants.delete const
+ @constants_hash.delete const.name
+ end
end
- class_module.each_include do |incl|
- add_include incl
+ merge_collections includes, class_module.includes do |add, incl|
+ if add then
+ add_include incl
+ else
+ @includes.delete incl
+ end
end
- class_module.each_method do |meth|
- add_method meth
+ merge_collections method_list, class_module.method_list do |add, meth|
+ if add then
+ add_method meth
+ else
+ @method_list.delete meth
+ @methods_hash.delete meth.pretty_name
+ end
+ end
+
+ self
+ end
+
+ ##
+ # Merges collection +mine+ with +other+ preferring other.
+
+ def merge_collections mine, other, &block # :nodoc:
+ my_things = mine. group_by { |thing| thing.file }
+ other_things = other.group_by { |thing| thing.file }
+
+ other_things.each do |file, things|
+ my_things[file].each { |thing| yield false, thing } if
+ my_things.include? file
+
+ things.each do |thing|
+ yield true, thing
+ end
end
end
@@ -309,6 +400,29 @@ class RDoc::ClassModule < RDoc::Context
end
##
+ # Parses +comment_location+ into an RDoc::Markup::Document composed of
+ # multiple RDoc::Markup::Documents with their file set.
+
+ def parse comment_location
+ case comment_location
+ when String then
+ super
+ when Array then
+ docs = comment_location.map do |comment, location|
+ doc = super comment
+ doc.file = location.absolute_name
+ doc
+ end
+
+ RDoc::Markup::Document.new(*docs)
+ when RDoc::Markup::Document then
+ return comment_location
+ else
+ raise ArgumentError, "unknown comment class #{comment_location.class}"
+ end
+ end
+
+ ##
# Path to this class or module
def path
diff --git a/lib/rdoc/code_object.rb b/lib/rdoc/code_object.rb
index 63f86afc64..606fd8ff49 100644
--- a/lib/rdoc/code_object.rb
+++ b/lib/rdoc/code_object.rb
@@ -130,7 +130,8 @@ class RDoc::CodeObject
# TODO is this sufficient?
# HACK correct fix is to have #initialize create @comment
# with the correct encoding
- if Object.const_defined? :Encoding and @comment.empty? then
+ if String === @comment and
+ Object.const_defined? :Encoding and @comment.empty? then
@comment.force_encoding comment.encoding
end
@comment
@@ -194,6 +195,12 @@ class RDoc::CodeObject
self
end
+ def file_name
+ return unless @file
+
+ @file.absolute_name
+ end
+
##
# Force the documentation of this object unless documentation
# has been turned off by :endoc:
diff --git a/lib/rdoc/context.rb b/lib/rdoc/context.rb
index f0168585ec..d2552c647c 100644
--- a/lib/rdoc/context.rb
+++ b/lib/rdoc/context.rb
@@ -30,9 +30,9 @@ class RDoc::Context < RDoc::CodeObject
attr_reader :constants
##
- # Current section of documentation
+ # Sets the current documentation section of documentation
- attr_accessor :current_section
+ attr_writer :current_section
##
# Files this context is found in
@@ -60,6 +60,11 @@ class RDoc::Context < RDoc::CodeObject
attr_reader :requires
##
+ # Use this section for the next method, attribute or constant added.
+
+ attr_accessor :temporary_section
+
+ ##
# 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.)
@@ -186,10 +191,7 @@ class RDoc::Context < RDoc::CodeObject
end
def inspect # :nodoc:
- "#<%s:0x%x %s %p>" % [
- self.class, object_id,
- @sequence, title
- ]
+ "#<%s:0x%x %p>" % [self.class, object_id, title]
end
##
@@ -216,6 +218,7 @@ class RDoc::Context < RDoc::CodeObject
@current_section = Section.new self, nil, nil
@sections = { nil => @current_section }
+ @temporary_section = nil
@classes = {}
@modules = {}
@@ -287,22 +290,32 @@ class RDoc::Context < RDoc::CodeObject
# TODO find a policy for 'attr_reader :foo' + 'def foo=()'
register = false
- if attribute.rw.index('R') then
+ key = nil
+
+ 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?
+ elsif registered = @methods_hash[attribute.pretty_name << '='] and
+ RDoc::Attr === registered then
+ registered.rw = 'RW'
else
@methods_hash[key] = attribute
register = true
end
end
- if attribute.rw.index('W')
+ if attribute.rw.index 'W' then
key = attribute.pretty_name << '='
known = @methods_hash[key]
+
if known then
known.comment = attribute.comment if known.comment.empty?
+ elsif registered = @methods_hash[attribute.pretty_name] and
+ RDoc::Attr === registered then
+ registered.rw = 'RW'
else
@methods_hash[key] = attribute
register = true
@@ -314,6 +327,8 @@ class RDoc::Context < RDoc::CodeObject
add_to @attributes, attribute
resolve_aliases attribute
end
+
+ attribute
end
##
@@ -444,8 +459,8 @@ class RDoc::Context < RDoc::CodeObject
# to +self+, and its #section to #current_section. Returns +mod+.
def add_class_or_module mod, self_hash, all_hash
- mod.section = @current_section # TODO declaring context? something is
- # wrong here...
+ mod.section = current_section # TODO declaring context? something is
+ # wrong here...
mod.parent = self
unless @done_documenting then
@@ -462,7 +477,7 @@ class RDoc::Context < RDoc::CodeObject
# 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)
+ def add_constant constant
return constant unless @document_self
# HACK: avoid duplicate 'PI' & 'E' in math.c (1.8.7 source code)
@@ -480,28 +495,32 @@ class RDoc::Context < RDoc::CodeObject
@constants_hash[constant.name] = constant
add_to @constants, constant
end
+
+ constant
end
##
# 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 )
+ def add_include include
+ add_to @includes, include unless
+ @includes.map { |i| i.full_name }.include? include.full_name
+
+ include
end
##
# Adds +method+ if not already there. If it is (as method or attribute),
# updates the comment if it was empty.
- def add_method(method)
+ def add_method method
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)}"
+
+ if known then
known.comment = method.comment if known.comment.empty?
else
@methods_hash[key] = method
@@ -509,6 +528,8 @@ class RDoc::Context < RDoc::CodeObject
add_to @method_list, method
resolve_aliases method
end
+
+ method
end
##
@@ -573,12 +594,31 @@ class RDoc::Context < RDoc::CodeObject
end
##
+ # Returns a section with +title+, creating it if it doesn't already exist.
+ # +comment+ will be appended to the section's comment.
+ #
+ # A section with a +title+ of +nil+ will return the default section.
+ #
+ # See also RDoc::Context::Section
+
+ def add_section title, comment
+ if section = @sections[title] then
+ section.comment = comment
+ else
+ section = Section.new self, title, comment
+ @sections[title] = section
+ end
+
+ section
+ end
+
+ ##
# Adds +thing+ to the collection +array+
def add_to(array, thing)
array << thing if @document_self
thing.parent = self
- thing.section = @current_section
+ thing.section = current_section
end
##
@@ -649,6 +689,20 @@ class RDoc::Context < RDoc::CodeObject
end
##
+ # The current documentation section that new items will be added to. If
+ # temporary_section is available it will be used.
+
+ def current_section
+ if section = @temporary_section then
+ @temporary_section = nil
+ else
+ section = @current_section
+ end
+
+ section
+ end
+
+ ##
# Is part of this thing was defined in +file+?
def defined_in?(file)
@@ -1082,18 +1136,10 @@ class RDoc::Context < RDoc::CodeObject
end
##
- # Creates a new section with +title+ and +comment+
-
- def set_current_section(title, comment)
- if @sections.key? title then
- @current_section = @sections[title]
- @current_section.comment = comment
- else
- @current_section = Section.new self, title, comment
- @sections[title] = @current_section
- end
+ # Sets the current section to a section with +title+. See also #add_section
- @current_section
+ def set_current_section title, comment
+ @current_section = add_section title, comment
end
##
diff --git a/lib/rdoc/generator/markup.rb b/lib/rdoc/generator/markup.rb
index 1919a62ec8..c267bb1c13 100644
--- a/lib/rdoc/generator/markup.rb
+++ b/lib/rdoc/generator/markup.rb
@@ -42,7 +42,9 @@ module RDoc::Generator::Markup
show_hash = RDoc::RDoc.current.options.show_hash
hyperlink_all = RDoc::RDoc.current.options.hyperlink_all
this = RDoc::Context === self ? self : @parent
- @formatter = RDoc::Markup::ToHtmlCrossref.new this.path, this, show_hash, hyperlink_all
+
+ @formatter = RDoc::Markup::ToHtmlCrossref.new(this.path, this, show_hash,
+ hyperlink_all)
end
##
diff --git a/lib/rdoc/generator/ri.rb b/lib/rdoc/generator/ri.rb
index e02805e40f..939a165cfb 100644
--- a/lib/rdoc/generator/ri.rb
+++ b/lib/rdoc/generator/ri.rb
@@ -18,11 +18,12 @@ class RDoc::Generator::RI
def initialize options #:not-new:
@options = options
- @store = RDoc::RI::Store.new '.'
@old_siginfo = nil
@current = nil
- @store.dry_run = @options.dry_run
+ @store = RDoc::RI::Store.new '.'
+ @store.dry_run = @options.dry_run
+ @store.encoding = @options.encoding if @options.respond_to? :encoding
end
##
diff --git a/lib/rdoc/generator/template/darkfish/rdoc.css b/lib/rdoc/generator/template/darkfish/rdoc.css
index c5a93ff150..ea91421837 100644
--- a/lib/rdoc/generator/template/darkfish/rdoc.css
+++ b/lib/rdoc/generator/template/darkfish/rdoc.css
@@ -97,6 +97,10 @@ body.file p {
margin: 1em 0;
}
+.indexpage .rdoc-list p, .file .rdoc-list p {
+ margin: 0em 0;
+}
+
.indexpage ol,
.file #documentation ol {
line-height: 160%;
diff --git a/lib/rdoc/known_classes.rb b/lib/rdoc/known_classes.rb
index eb90185f53..3feb31eae1 100644
--- a/lib/rdoc/known_classes.rb
+++ b/lib/rdoc/known_classes.rb
@@ -36,7 +36,7 @@ module RDoc
"rb_eArgError" => "ArgError",
"rb_eEOFError" => "EOFError",
"rb_eException" => "Exception",
- "rb_eFatal" => "Fatal",
+ "rb_eFatal" => "fatal",
"rb_eFloatDomainError" => "FloatDomainError",
"rb_eIOError" => "IOError",
"rb_eIndexError" => "IndexError",
@@ -49,7 +49,7 @@ module RDoc
"rb_eRuntimeError" => "RuntimeError",
"rb_eScriptError" => "ScriptError",
"rb_eSecurityError" => "SecurityError",
- "rb_eSignal" => "Signal",
+ "rb_eSignal" => "SignalException",
"rb_eStandardError" => "StandardError",
"rb_eSyntaxError" => "SyntaxError",
"rb_eSystemCallError" => "SystemCallError",
diff --git a/lib/rdoc/markup.rb b/lib/rdoc/markup.rb
index 73de2d06f8..bc28522615 100644
--- a/lib/rdoc/markup.rb
+++ b/lib/rdoc/markup.rb
@@ -48,13 +48,13 @@ require 'rdoc'
# end
# end
#
-# m = RDoc::Markup.new
-# m.add_word_pair("{", "}", :STRIKE)
-# m.add_html("no", :STRIKE)
+# markup = RDoc::Markup.new
+# markup.add_word_pair("{", "}", :STRIKE)
+# markup.add_html("no", :STRIKE)
#
-# m.add_special(/\b([A-Z][a-z]+[A-Z]\w+)/, :WIKIWORD)
+# markup.add_special(/\b([A-Z][a-z]+[A-Z]\w+)/, :WIKIWORD)
#
-# wh = WikiHtml.new
+# wh = WikiHtml.new markup
# wh.add_tag(:STRIKE, "<strike>", "</strike>")
#
# puts "<body>#{wh.convert ARGF.read}</body>"
@@ -498,15 +498,53 @@ require 'rdoc'
# [+:main:+ _name_]
# Equivalent to the <tt>--main</tt> command line parameter.
#
+# [<tt>:category: section</tt>]
+# Adds this item to the named +section+ overriding the current section. Use
+# this to group methods by section in RDoc output while maintaining a
+# sensible ordering (like alphabetical).
+#
+# # :category: Utility Methods
+# #
+# # CGI escapes +text+
+#
+# def convert_string text
+# CGI.escapeHTML text
+# end
+#
+# An empty category will place the item in the default category:
+#
+# # :category:
+# #
+# # This method is in the default category
+#
+# def some_method
+# # ...
+# end
+#
+# Unlike the :section: directive, :category: is not sticky. The category
+# only applies to the item immediately following the comment.
+#
+# Use the :section: directive to provide introductory text for a section of
+# documentation.
+#
# [<tt>:section: title</tt>]
-# Starts a new section in the output. The title following +:section:+ is
-# used as the section heading, and the remainder of the comment containing
-# the section is used as introductory text. Subsequent methods, aliases,
-# attributes, and classes will be documented in this section.
+# Provides section introductory text in RDoc output. The title following
+# +:section:+ is used as the section name and the remainder of the comment
+# containing the section is used as introductory text. A section's comment
+# block must be separated from following comment blocks. Use an empty title
+# to switch to the default section.
+#
+# The :section: directive is sticky, so subsequent methods, aliases,
+# attributes, and classes will be contained in this section until the
+# section is changed. The :category: directive will override the :section:
+# directive.
#
# A :section: comment block may have one or more lines before the :section:
# directive. These will be removed, and any identical lines at the end of
-# the block are also removed. This allows you to add visual cues such as:
+# the block are also removed. This allows you to add visual cues to the
+# section.
+#
+# Example:
#
# # ----------------------------------------
# # :section: My Section
@@ -514,10 +552,12 @@ require 'rdoc'
# # See it glisten in the noon-day sun.
# # ----------------------------------------
#
-# Sections may be referenced multiple times in a class or module allowing
-# methods, attributes and constants to be ordered one way for implementation
-# ordering but still grouped together in documentation. If a section has
-# multiple comments they will be concatenated with a dividing rule.
+# ##
+# # Comment for some_method
+#
+# def some_method
+# # ...
+# end
#
# [+:call-seq:+]
# Lines up to the next blank line in the comment are treated as the method's
diff --git a/lib/rdoc/markup/document.rb b/lib/rdoc/markup/document.rb
index 688e8e822e..b4e070285e 100644
--- a/lib/rdoc/markup/document.rb
+++ b/lib/rdoc/markup/document.rb
@@ -4,6 +4,12 @@
class RDoc::Markup::Document
##
+ # The file this document was created from. See also
+ # RDoc::ClassModule#add_comment
+
+ attr_accessor :file
+
+ ##
# The parts of the Document
attr_reader :parts
@@ -14,6 +20,8 @@ class RDoc::Markup::Document
def initialize *parts
@parts = []
@parts.push(*parts)
+
+ @file = nil
end
##
@@ -36,7 +44,9 @@ class RDoc::Markup::Document
end
def == other # :nodoc:
- self.class == other.class and @parts == other.parts
+ self.class == other.class and
+ @file == other.file and
+ @parts == other.parts
end
##
@@ -59,8 +69,30 @@ class RDoc::Markup::Document
@parts.empty?
end
+ ##
+ # When this is a collection of documents (#file is not set and this document
+ # contains only other documents as its direct children) #merge replaces
+ # documents in this class with documents from +other+ when the file matches
+ # and adds documents from +other+ when the files do not.
+ #
+ # The information in +other+ is preferred over the receiver
+
+ def merge other
+ other.parts.each do |other_part|
+ self.parts.delete_if do |self_part|
+ self_part.file and self_part.file == other_part.file
+ end
+
+ self.parts << other_part
+ end
+
+ self
+ end
+
def pretty_print q # :nodoc:
- q.group 2, '[doc: ', ']' do
+ start = @file ? "[doc (#{@file}): " : '[doc: '
+
+ q.group 2, start, ']' do
q.seplist @parts do |part|
q.pp part
end
diff --git a/lib/rdoc/markup/formatter.rb b/lib/rdoc/markup/formatter.rb
index 9308954de1..b6e12f82e7 100644
--- a/lib/rdoc/markup/formatter.rb
+++ b/lib/rdoc/markup/formatter.rb
@@ -16,9 +16,10 @@ class RDoc::Markup::Formatter
##
# Creates a new Formatter
- def initialize
- @markup = RDoc::Markup.new
- @am = @markup.attribute_manager
+ def initialize markup = nil
+ @markup = markup || RDoc::Markup.new
+ @am = @markup.attribute_manager
+
@attr_tags = []
@in_tt = 0
@@ -26,6 +27,15 @@ class RDoc::Markup::Formatter
end
##
+ # Adds +document+ to the output
+
+ def accept_document document
+ document.parts.each do |item|
+ item.accept self
+ end
+ end
+
+ ##
# Add a new set of tags for an attribute. We allow separate start and end
# tags for flexibility
diff --git a/lib/rdoc/markup/formatter_test_case.rb b/lib/rdoc/markup/formatter_test_case.rb
index 26dc4b25e9..c739f990b3 100644
--- a/lib/rdoc/markup/formatter_test_case.rb
+++ b/lib/rdoc/markup/formatter_test_case.rb
@@ -120,6 +120,16 @@ class RDoc::Markup::FormatterTestCase < MiniTest::Unit::TestCase
end
##
+ # Test case that calls <tt>@to.accept_document</tt>
+
+ def test_accept_document
+ @to.start_accepting
+ @to.accept_document @RM::Document.new @RM::Paragraph.new 'hello'
+
+ accept_document
+ end
+
+ ##
# Calls accept_heading with a level 5 RDoc::Markup::Heading
def test_accept_heading
diff --git a/lib/rdoc/markup/indented_paragraph.rb b/lib/rdoc/markup/indented_paragraph.rb
new file mode 100644
index 0000000000..d995c7d8ed
--- /dev/null
+++ b/lib/rdoc/markup/indented_paragraph.rb
@@ -0,0 +1,33 @@
+##
+# An Indented Paragraph of text
+
+class RDoc::Markup::IndentedParagraph < RDoc::Markup::Raw
+
+ ##
+ # The indent in number of spaces
+
+ attr_reader :indent
+
+ ##
+ # Creates a new IndentedParagraph containing +parts+ indented with +indent+
+ # spaces
+
+ def initialize indent, *parts
+ @indent = indent
+
+ super(*parts)
+ end
+
+ def == other # :nodoc:
+ super and indent == other.indent
+ end
+
+ ##
+ # Calls #accept_indented_paragraph on +visitor+
+
+ def accept visitor
+ visitor.accept_indented_paragraph self
+ end
+
+end
+
diff --git a/lib/rdoc/markup/parser.rb b/lib/rdoc/markup/parser.rb
index c94b900154..68616d7787 100644
--- a/lib/rdoc/markup/parser.rb
+++ b/lib/rdoc/markup/parser.rb
@@ -478,6 +478,7 @@ require 'rdoc/markup/list'
require 'rdoc/markup/list_item'
require 'rdoc/markup/raw'
require 'rdoc/markup/paragraph'
+require 'rdoc/markup/indented_paragraph'
require 'rdoc/markup/rule'
require 'rdoc/markup/verbatim'
diff --git a/lib/rdoc/markup/pre_process.rb b/lib/rdoc/markup/pre_process.rb
index ccc2688050..03f919aa0e 100644
--- a/lib/rdoc/markup/pre_process.rb
+++ b/lib/rdoc/markup/pre_process.rb
@@ -74,6 +74,13 @@ class RDoc::Markup::PreProcess
filename = param.split[0]
encoding = if defined?(Encoding) then text.encoding else nil end
include_file filename, prefix, encoding
+ when 'category' then
+ if RDoc::Context === code_object then
+ section = code_object.add_section param, ''
+ code_object.temporary_section = section
+ end
+
+ '' # ignore category if we're not on an RDoc::Context
else
result = yield directive, param if block_given?
diff --git a/lib/rdoc/markup/to_ansi.rb b/lib/rdoc/markup/to_ansi.rb
index c9f874ea3c..108a038075 100644
--- a/lib/rdoc/markup/to_ansi.rb
+++ b/lib/rdoc/markup/to_ansi.rb
@@ -8,7 +8,7 @@ class RDoc::Markup::ToAnsi < RDoc::Markup::ToRdoc
##
# Creates a new ToAnsi visitor that is ready to output vibrant ANSI color!
- def initialize
+ def initialize markup = nil
super
@headings.clear
diff --git a/lib/rdoc/markup/to_bs.rb b/lib/rdoc/markup/to_bs.rb
index 931edd81ea..32b1bbb9eb 100644
--- a/lib/rdoc/markup/to_bs.rb
+++ b/lib/rdoc/markup/to_bs.rb
@@ -11,7 +11,7 @@ class RDoc::Markup::ToBs < RDoc::Markup::ToRdoc
##
# Returns a new ToBs that is ready for hot backspace action!
- def initialize
+ def initialize markup = nil
super
@in_b = false
diff --git a/lib/rdoc/markup/to_html.rb b/lib/rdoc/markup/to_html.rb
index 599f3713f1..b518fbf265 100644
--- a/lib/rdoc/markup/to_html.rb
+++ b/lib/rdoc/markup/to_html.rb
@@ -17,7 +17,7 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
LIST_TYPE_TO_HTML = {
:BULLET => ['<ul>', '</ul>'],
- :LABEL => ['<dl>', '</dl>'],
+ :LABEL => ['<dl class="rdoc-list">', '</dl>'],
:LALPHA => ['<ol style="display: lower-alpha">', '</ol>'],
:NOTE => ['<table class="rdoc-list">', '</table>'],
:NUMBER => ['<ol>', '</ol>'],
@@ -62,7 +62,7 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
##
# Creates a new formatter that will output HTML
- def initialize
+ def initialize markup = nil
super
@th = nil
diff --git a/lib/rdoc/markup/to_html_crossref.rb b/lib/rdoc/markup/to_html_crossref.rb
index 026defb862..aeecc3f4d0 100644
--- a/lib/rdoc/markup/to_html_crossref.rb
+++ b/lib/rdoc/markup/to_html_crossref.rb
@@ -104,9 +104,10 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
# references are removed unless +show_hash+ is true. Only method names
# preceded by '#' or '::' are hyperlinked, unless +hyperlink_all+ is true.
- def initialize(from_path, context, show_hash, hyperlink_all = false)
+ def initialize(from_path, context, show_hash, hyperlink_all = false,
+ markup = nil)
raise ArgumentError, 'from_path cannot be nil' if from_path.nil?
- super()
+ super markup
crossref_re = hyperlink_all ? ALL_CROSSREF_REGEXP : CROSSREF_REGEXP
diff --git a/lib/rdoc/markup/to_rdoc.rb b/lib/rdoc/markup/to_rdoc.rb
index b10af036d9..6f2faac2f6 100644
--- a/lib/rdoc/markup/to_rdoc.rb
+++ b/lib/rdoc/markup/to_rdoc.rb
@@ -44,7 +44,7 @@ class RDoc::Markup::ToRdoc < RDoc::Markup::Formatter
##
# Creates a new formatter that will output (mostly) \RDoc markup
- def initialize
+ def initialize markup = nil
super
@markup.add_special(/\\\S/, :SUPPRESSED_CROSSREF)
@@ -172,6 +172,15 @@ class RDoc::Markup::ToRdoc < RDoc::Markup::Formatter
end
##
+ # Adds +paragraph+ to the output
+
+ def accept_indented_paragraph paragraph
+ @indent += paragraph.indent
+ wrap attributes(paragraph.text)
+ @indent -= paragraph.indent
+ end
+
+ ##
# Adds +raw+ to the output
def accept_raw raw
diff --git a/lib/rdoc/markup/to_test.rb b/lib/rdoc/markup/to_test.rb
index f79f9475f1..4847fd29f7 100644
--- a/lib/rdoc/markup/to_test.rb
+++ b/lib/rdoc/markup/to_test.rb
@@ -21,7 +21,7 @@ class RDoc::Markup::ToTest < RDoc::Markup::Formatter
end
def accept_paragraph(paragraph)
- @res << paragraph.text
+ @res << convert_flow(@am.flow(paragraph.text))
end
def accept_raw raw
diff --git a/lib/rdoc/markup/to_tt_only.rb b/lib/rdoc/markup/to_tt_only.rb
index 98ad2f6936..078e87db98 100644
--- a/lib/rdoc/markup/to_tt_only.rb
+++ b/lib/rdoc/markup/to_tt_only.rb
@@ -20,7 +20,7 @@ class RDoc::Markup::ToTtOnly < RDoc::Markup::Formatter
##
# Creates a new tt-only formatter.
- def initialize
+ def initialize markup = nil
super
add_tag :TT, nil, nil
diff --git a/lib/rdoc/parser/c.rb b/lib/rdoc/parser/c.rb
index 12efb407a2..7d05d12fb4 100644
--- a/lib/rdoc/parser/c.rb
+++ b/lib/rdoc/parser/c.rb
@@ -1,4 +1,4 @@
-require 'rdoc/parser'
+
require 'rdoc/parser/ruby'
require 'rdoc/known_classes'
@@ -64,8 +64,17 @@ require 'rdoc/known_classes'
# [Document-variable: +name+]
# Documentation for the named +rb_define_variable+
#
-# [Document-method: +name+]
-# Documentation for the named method.
+# [Document-method: +method_name+]
+# Documentation for the named method. Use this when the method name is
+# unambiguous.
+#
+# [Document-method: <tt>ClassName::method_name<tt>]
+# Documentation for a singleton method in the given class. Use this when
+# the method name alone is ambiguous.
+#
+# [Document-method: <tt>ClassName#method_name<tt>]
+# Documentation for a instance method in the given class. Use this when the
+# method name alone is ambiguous.
#
# [Document-attr: +name+]
# Documentation for the named attribute.
@@ -113,6 +122,17 @@ class RDoc::Parser::C < RDoc::Parser
attr_accessor :content
+
+ ##
+ # Maps C variable names to names of ruby classes (andsingleton classes)
+
+ attr_reader :known_classes
+
+ ##
+ # Maps C variable names to names of ruby singleton classes
+
+ attr_reader :singleton_classes
+
##
# Resets cross-file state. Call when parsing different projects that need
# separate documentation.
@@ -132,8 +152,8 @@ class RDoc::Parser::C < RDoc::Parser
@known_classes = RDoc::KNOWN_CLASSES.dup
@content = handle_tab_width handle_ifdefs_in(@content)
- @classes = Hash.new
- @singleton_classes = Hash.new
+ @classes = {}
+ @singleton_classes = {}
@file_dir = File.dirname(@file_name)
end
@@ -146,17 +166,25 @@ class RDoc::Parser::C < RDoc::Parser
\s*"(.+?)",
\s*"(.+?)"
\s*\)/xm) do |var_name, new_name, old_name|
- class_name = @known_classes[var_name] || var_name
- class_obj = find_class var_name, class_name
+ class_name = @known_classes[var_name]
+
+ unless class_name then
+ warn "Enclosing class/module %p for alias %s %s not known" % [
+ var_name, new_name, old_name]
+ next
+ end
+
+ class_obj = find_class var_name, class_name
al = RDoc::Alias.new '', old_name, new_name, ''
- al.singleton = @singleton_classes.key?(var_name)
+ al.singleton = @singleton_classes.key? var_name
comment = find_alias_comment var_name, new_name, old_name
comment = strip_stars comment
al.comment = comment
al.record_location @top_level
+
class_obj.add_alias al
@stats.add_alias al
end
@@ -262,6 +290,18 @@ class RDoc::Parser::C < RDoc::Parser
var_name = "rb_cObject" if !var_name or var_name == "rb_mKernel"
handle_constants type, var_name, const_name, definition
end
+
+ @content.scan(%r%
+ \Wrb_curses_define_const
+ \s*\(
+ \s*
+ (\w+)
+ \s*
+ \)
+ \s*;%xm) do |consts|
+ const = consts.first
+ handle_constants 'const', 'mCurses', const, "UINT2NUM(#{const})"
+ end
end
##
@@ -271,7 +311,8 @@ class RDoc::Parser::C < RDoc::Parser
@content.scan(/rb_include_module\s*\(\s*(\w+?),\s*(\w+?)\s*\)/) do |c,m|
if cls = @classes[c]
m = @known_classes[m] || m
- cls.add_include RDoc::Include.new(m, "")
+ incl = cls.add_include RDoc::Include.new(m, "")
+ incl.record_location @top_level
end
end
end
@@ -293,7 +334,7 @@ class RDoc::Parser::C < RDoc::Parser
\s*"([^"]+)",
\s*(?:RUBY_METHOD_FUNC\(|VALUEFUNC\()?(\w+)\)?,
\s*(-?\w+)\s*\)
- (?:;\s*/[*/]\s+in\s+(\w+?\.[cy]))?
+ (?:;\s*/[*/]\s+in\s+(\w+?\.(?:cpp|c|y)))?
%xm) do |type, var_name, meth_name, function, param_count, source_file|
# Ignore top-object and weird struct.c dynamic stuff
@@ -401,7 +442,7 @@ class RDoc::Parser::C < RDoc::Parser
# distinct (for example Kernel.hash and Kernel.object_id share the same
# implementation
- override_comment = find_override_comment class_name, meth_obj.name
+ override_comment = find_override_comment class_name, meth_obj
comment = override_comment if override_comment
find_modifiers comment, meth_obj if comment
@@ -444,7 +485,7 @@ class RDoc::Parser::C < RDoc::Parser
warn "No definition for #{meth_name}" if @options.verbosity > 1
false
else # No body, but might still have an override comment
- comment = find_override_comment class_name, meth_obj.name
+ comment = find_override_comment class_name, meth_obj
if comment then
find_modifiers comment, meth_obj
@@ -524,21 +565,26 @@ class RDoc::Parser::C < RDoc::Parser
comment = look_for_directives_in class_mod, comment
- class_mod.comment = comment
+ class_mod.add_comment comment, @top_level
end
##
# Finds a comment matching +type+ and +const_name+ either above the
# comment or in the matching Document- section.
- def find_const_comment(type, const_name)
+ def find_const_comment(type, const_name, class_name = nil)
if @content =~ %r%((?>^\s*/\*.*?\*/\s+))
rb_define_#{type}\((?:\s*(\w+),)?\s*
"#{const_name}"\s*,
.*?\)\s*;%xmi then
$1
+ elsif class_name and
+ @content =~ %r%Document-(?:const|global|variable):\s
+ #{class_name}::#{const_name}
+ \s*?\n((?>.*?\*/))%xm then
+ $1
elsif @content =~ %r%Document-(?:const|global|variable):\s#{const_name}
- \s*?\n((?>.*?\*/))%xm
+ \s*?\n((?>.*?\*/))%xm then
$1
else
''
@@ -607,12 +653,13 @@ class RDoc::Parser::C < RDoc::Parser
end
##
- # Finds a <tt>Document-method</tt> override for +meth_name+ in +class_name+
+ # Finds a <tt>Document-method</tt> override for +meth_obj+ on +class_name+
- def find_override_comment(class_name, meth_name)
- name = Regexp.escape(meth_name)
+ def find_override_comment class_name, meth_obj
+ name = Regexp.escape meth_obj.name
+ prefix = Regexp.escape meth_obj.name_prefix
- if @content =~ %r%Document-method:\s+#{class_name}(?:\.|::|#)#{name}\s*?\n((?>.*?\*/))%m then
+ if @content =~ %r%Document-method:\s+#{class_name}#{prefix}#{name}\s*?\n((?>.*?\*/))%m then
$1
elsif @content =~ %r%Document-method:\s#{name}\s*?\n((?>.*?\*/))%m then
$1
@@ -726,7 +773,7 @@ class RDoc::Parser::C < RDoc::Parser
return
end
- comment = find_const_comment type, const_name
+ comment = find_const_comment type, const_name, class_name
comment = strip_stars comment
comment = normalize_comment comment
@@ -781,13 +828,8 @@ class RDoc::Parser::C < RDoc::Parser
def handle_method(type, var_name, meth_name, function, param_count,
source_file = nil)
- singleton = false
class_name = @known_classes[var_name]
-
- unless class_name then
- class_name = @singleton_classes[var_name]
- singleton = true if class_name
- end
+ singleton = @singleton_classes.key? var_name
return unless class_name
@@ -845,6 +887,7 @@ class RDoc::Parser::C < RDoc::Parser
def handle_singleton sclass_var, class_var
class_name = @known_classes[class_var]
+ @known_classes[sclass_var] = class_name
@singleton_classes[sclass_var] = class_name
end
diff --git a/lib/rdoc/parser/ruby.rb b/lib/rdoc/parser/ruby.rb
index 4d273598be..50071ab736 100644
--- a/lib/rdoc/parser/ruby.rb
+++ b/lib/rdoc/parser/ruby.rb
@@ -350,7 +350,9 @@ class RDoc::Parser::Ruby < RDoc::Parser
def get_constant_with_optional_parens
skip_tkspace false
+
nest = 0
+
while TkLPAREN === (tk = peek_tk) or TkfLPAREN === tk do
get_tk
skip_tkspace
@@ -631,7 +633,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
cls.offset = offset
cls.line = line_no
- cls.comment = comment if cls.document_self
+ cls.add_comment comment, @top_level if cls.document_self
@top_level.add_to_classes_or_modules cls
@stats.add_class cls
@@ -650,7 +652,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
other.offset = offset
other.line = line_no
- other.comment = comment
+ other.add_comment comment, @top_level
end
# notify :nodoc: all if not a constant-named class/module
@@ -826,14 +828,19 @@ class RDoc::Parser::Ruby < RDoc::Parser
##
# Parses an +include+ in +context+ with +comment+
- def parse_include(context, comment)
+ def parse_include context, comment
loop do
skip_tkspace_comment
name = get_constant_with_optional_parens
- context.add_include RDoc::Include.new(name, comment) unless name.empty?
+
+ unless name.empty? then
+ incl = context.add_include RDoc::Include.new(name, comment)
+ incl.record_location @top_level
+ end
return unless TkCOMMA === peek_tk
+
get_tk
end
end
@@ -1231,7 +1238,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
mod.record_location @top_level
read_documentation_modifiers mod, RDoc::CLASS_MODIFIERS
- mod.comment = comment if mod.document_self
+ mod.add_comment comment, @top_level if mod.document_self
parse_statements(mod)
@top_level.add_to_classes_or_modules mod
@@ -1295,9 +1302,12 @@ class RDoc::Parser::Ruby < RDoc::Parser
while TkCOMMENT === tk do
comment << tk.text << "\n"
- tk = get_tk # this is the newline
- skip_tkspace false # leading spaces
tk = get_tk
+
+ if TkNL === tk then
+ skip_tkspace false # leading spaces
+ tk = get_tk
+ end
end
unless comment.empty? then
@@ -1313,7 +1323,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
non_comment_seen = true
end
- unget_tk tk
+ unget_tk tk # TODO peek instead of get then unget
keep_comment = true
when TkCLASS then
diff --git a/lib/rdoc/rdoc.rb b/lib/rdoc/rdoc.rb
index 6d7c4eace6..95ba9ae8ab 100644
--- a/lib/rdoc/rdoc.rb
+++ b/lib/rdoc/rdoc.rb
@@ -101,6 +101,14 @@ class RDoc::RDoc
end
##
+ # Resets all internal state
+
+ def self.reset
+ RDoc::TopLevel.reset
+ RDoc::Parser::C.reset
+ end
+
+ ##
# Creates a new RDoc::RDoc instance. Call #document to parse files and
# generate documentation.
@@ -306,8 +314,12 @@ option)
# Parses +filename+ and returns an RDoc::TopLevel
def parse_file filename
+ if defined?(Encoding) then
+ encoding = @options.encoding
+ filename = filename.encode encoding
+ end
+
@stats.add_file filename
- encoding = @options.encoding if defined?(Encoding)
content = RDoc::Encoding.read_file filename, encoding
@@ -396,8 +408,7 @@ The internal error was:
# current directory, so make sure you're somewhere writable before invoking.
def document options
- RDoc::TopLevel.reset
- RDoc::Parser::C.reset
+ RDoc::RDoc.reset
if RDoc::Options === options then
@options = options
diff --git a/lib/rdoc/ri/driver.rb b/lib/rdoc/ri/driver.rb
index 46aeaeebc2..2c6f2f48e2 100644
--- a/lib/rdoc/ri/driver.rb
+++ b/lib/rdoc/ri/driver.rb
@@ -456,9 +456,13 @@ Options may also be set in the 'RI' environment variable.
out << RDoc::Markup::Heading.new(1, "#{name}:")
out << RDoc::Markup::BlankLine.new
- out.push(*methods.map do |method|
- RDoc::Markup::Verbatim.new method
- end)
+ if @use_stdout and !@interactive
+ out.push(*methods.map do |method|
+ RDoc::Markup::Verbatim.new method
+ end)
+ else
+ out << RDoc::Markup::IndentedParagraph.new(2, methods.join(', '))
+ end
out << RDoc::Markup::BlankLine.new
end
@@ -532,8 +536,9 @@ Options may also be set in the 'RI' environment variable.
klass_name = method ? name : klass
if name !~ /#|\./ then
- completions = klasses.grep(/^#{klass_name}[^:]*$/)
- completions.concat klasses.grep(/^#{name}[^:]*$/) if name =~ /::$/
+ completions = klasses.grep(/^#{Regexp.escape klass_name}[^:]*$/)
+ completions.concat klasses.grep(/^#{Regexp.escape name}[^:]*$/) if
+ name =~ /::$/
completions << klass if classes.key? klass # to complete a method name
elsif selector then
diff --git a/lib/rdoc/ri/store.rb b/lib/rdoc/ri/store.rb
index c3939c493a..e48386adcb 100644
--- a/lib/rdoc/ri/store.rb
+++ b/lib/rdoc/ri/store.rb
@@ -19,6 +19,8 @@ require 'fileutils'
# :modules => [], # classes and modules in this store
# :ancestors => {}, # class name => ancestor names
# }
+#--
+# TODO need to store the list of files and prune classes
class RDoc::RI::Store
@@ -44,19 +46,26 @@ class RDoc::RI::Store
attr_reader :cache
##
+ # The encoding of the contents in the Store
+
+ attr_accessor :encoding
+
+ ##
# Creates a new Store of +type+ that will load or save to +path+
def initialize path, type = nil
- @dry_run = false
- @type = type
- @path = path
+ @dry_run = false
+ @type = type
+ @path = path
+ @encoding = nil
@cache = {
+ :ancestors => {},
+ :attributes => {},
:class_methods => {},
+ :encoding => @encoding,
:instance_methods => {},
- :attributes => {},
:modules => [],
- :ancestors => {},
}
end
@@ -107,6 +116,22 @@ class RDoc::RI::Store
end
##
+ # Removes empty items and ensures item in each collection are unique and
+ # sorted
+
+ def clean_cache_collection collection # :nodoc:
+ collection.each do |name, item|
+ if item.empty? then
+ collection.delete name
+ else
+ # HACK mongrel-1.1.5 documents its files twice
+ item.uniq!
+ item.sort!
+ end
+ end
+ end
+
+ ##
# Friendly rendition of #path
def friendly_path
@@ -138,9 +163,29 @@ class RDoc::RI::Store
# Loads cache file for this store
def load_cache
+ #orig_enc = @encoding
+
open cache_path, 'rb' do |io|
@cache = Marshal.load io.read
end
+
+ load_enc = @cache[:encoding]
+
+ # TODO this feature will be time-consuming to add:
+ # a) Encodings may be incompatible but transcodeable
+ # b) Need to warn in the appropriate spots, wherever they may be
+ # c) Need to handle cross-cache differences in encodings
+ # d) Need to warn when generating into a cache with diffent encodings
+ #
+ #if orig_enc and load_enc != orig_enc then
+ # warn "Cached encoding #{load_enc} is incompatible with #{orig_enc}\n" \
+ # "from #{path}/cache.ri" unless
+ # Encoding.compatible? orig_enc, load_enc
+ #end
+
+ @encoding = load_enc unless @encoding
+
+ @cache
rescue Errno::ENOENT
end
@@ -192,17 +237,21 @@ class RDoc::RI::Store
# Writes the cache file for this store
def save_cache
- # HACK mongrel-1.1.5 documents its files twice
- @cache[:ancestors]. each do |_, m| m.uniq!; m.sort! end
- @cache[:attributes]. each do |_, m| m.uniq!; m.sort! end
- @cache[:class_methods]. each do |_, m| m.uniq!; m.sort! end
- @cache[:instance_methods].each do |_, m| m.uniq!; m.sort! end
- @cache[:modules].uniq!; @cache[:modules].sort!
+ clean_cache_collection @cache[:ancestors]
+ clean_cache_collection @cache[:attributes]
+ clean_cache_collection @cache[:class_methods]
+ clean_cache_collection @cache[:instance_methods]
+
+ @cache[:modules].uniq!
+ @cache[:modules].sort!
+ @cache[:encoding] = @encoding # this gets set twice due to assert_cache
return if @dry_run
+ marshal = Marshal.dump @cache
+
open cache_path, 'wb' do |io|
- Marshal.dump @cache, io
+ io.write marshal
end
end
@@ -210,11 +259,13 @@ class RDoc::RI::Store
# Writes the ri data for +klass+
def save_class klass
- FileUtils.mkdir_p class_path(klass.full_name) unless @dry_run
+ full_name = klass.full_name
+
+ FileUtils.mkdir_p class_path(full_name) unless @dry_run
- @cache[:modules] << klass.full_name
+ @cache[:modules] << full_name
- path = class_file klass.full_name
+ path = class_file full_name
begin
disk_klass = nil
@@ -223,7 +274,7 @@ class RDoc::RI::Store
disk_klass = Marshal.load io.read
end
- klass.merge disk_klass
+ klass = disk_klass.merge klass
rescue Errno::ENOENT
end
@@ -233,22 +284,52 @@ class RDoc::RI::Store
String === ancestor ? ancestor : ancestor.full_name
end
- @cache[:ancestors][klass.full_name] ||= []
- @cache[:ancestors][klass.full_name].push(*ancestors)
+ @cache[:ancestors][full_name] ||= []
+ @cache[:ancestors][full_name].push(*ancestors)
attributes = klass.attributes.map do |attribute|
"#{attribute.definition} #{attribute.name}"
end
unless attributes.empty? then
- @cache[:attributes][klass.full_name] ||= []
- @cache[:attributes][klass.full_name].push(*attributes)
+ @cache[:attributes][full_name] ||= []
+ @cache[:attributes][full_name].push(*attributes)
+ end
+
+ to_delete = []
+
+ unless klass.method_list.empty? then
+ @cache[:class_methods][full_name] ||= []
+ @cache[:instance_methods][full_name] ||= []
+
+ class_methods, instance_methods =
+ klass.method_list.partition { |meth| meth.singleton }
+
+ class_methods = class_methods. map { |method| method.name }
+ instance_methods = instance_methods.map { |method| method.name }
+
+ old = @cache[:class_methods][full_name] - class_methods
+ to_delete.concat old.map { |method|
+ method_file full_name, "#{full_name}::#{method}"
+ }
+
+ old = @cache[:instance_methods][full_name] - instance_methods
+ to_delete.concat old.map { |method|
+ method_file full_name, "#{full_name}##{method}"
+ }
+
+ @cache[:class_methods][full_name] = class_methods
+ @cache[:instance_methods][full_name] = instance_methods
end
return if @dry_run
+ FileUtils.rm_f to_delete
+
+ marshal = Marshal.dump klass
+
open path, 'wb' do |io|
- Marshal.dump klass, io
+ io.write marshal
end
end
@@ -256,20 +337,24 @@ class RDoc::RI::Store
# Writes the ri data for +method+ on +klass+
def save_method klass, method
- FileUtils.mkdir_p class_path(klass.full_name) unless @dry_run
+ full_name = klass.full_name
+
+ FileUtils.mkdir_p class_path(full_name) unless @dry_run
cache = if method.singleton then
@cache[:class_methods]
else
@cache[:instance_methods]
end
- cache[klass.full_name] ||= []
- cache[klass.full_name] << method.name
+ cache[full_name] ||= []
+ cache[full_name] << method.name
return if @dry_run
- open method_file(klass.full_name, method.full_name), 'wb' do |io|
- Marshal.dump method, io
+ marshal = Marshal.dump method
+
+ open method_file(full_name, method.full_name), 'wb' do |io|
+ io.write marshal
end
end
diff --git a/lib/rdoc/rubygems_hook.rb b/lib/rdoc/rubygems_hook.rb
new file mode 100644
index 0000000000..178ca1d2ae
--- /dev/null
+++ b/lib/rdoc/rubygems_hook.rb
@@ -0,0 +1,220 @@
+require 'rubygems'
+require 'rubygems/user_interaction'
+require 'fileutils'
+require 'rdoc'
+
+##
+# Gem::RDoc provides methods to generate RDoc and ri data for installed gems
+# upon gem installation.
+#
+# This file is automatically required by RubyGems 1.9 and newer.
+
+class RDoc::RubygemsHook
+
+ include Gem::UserInteraction
+
+ @rdoc_version = nil
+ @specs = []
+
+ ##
+ # Force installation of documentation?
+
+ attr_accessor :force
+
+ ##
+ # Generate rdoc?
+
+ attr_accessor :generate_rdoc
+
+ ##
+ # Generate ri data?
+
+ attr_accessor :generate_ri
+
+ class << self
+
+ ##
+ # Loaded version of RDoc. Set by ::load_rdoc
+
+ attr_reader :rdoc_version
+
+ end
+
+ ##
+ # Post installs hook that generates documentation for each specification in
+ # +specs+
+
+ def self.generation_hook installer, specs
+ types = installer.document
+
+ generate_rdoc = types.include? 'rdoc'
+ generate_ri = types.include? 'ri'
+
+ specs.each do |spec|
+ new(spec, generate_rdoc, generate_ri).generate
+ end
+ end
+
+ ##
+ # Loads the RDoc generator
+
+ def self.load_rdoc
+ return if @rdoc_version
+
+ require 'rdoc/rdoc'
+
+ @rdoc_version = Gem::Version.new ::RDoc::VERSION
+ end
+
+ ##
+ # Creates a new documentation generator for +spec+. RDoc and ri data
+ # generation can be disabled through +generate_rdoc+ and +generate_ri+
+ # respectively.
+
+ def initialize spec, generate_rdoc = true, generate_ri = true
+ @doc_dir = spec.doc_dir
+ @file_info = nil
+ @force = false
+ @rdoc = nil
+ @spec = spec
+
+ @generate_rdoc = generate_rdoc
+ @generate_ri = generate_ri
+
+ @rdoc_dir = spec.doc_dir 'rdoc'
+ @ri_dir = spec.doc_dir 'ri'
+ end
+
+ ##
+ # Removes legacy rdoc arguments from +args+
+ #--
+ # TODO move to RDoc::Options
+
+ def delete_legacy_args args
+ args.delete '--inline-source'
+ args.delete '--promiscuous'
+ args.delete '-p'
+ args.delete '--one-file'
+ end
+
+ ##
+ # Generates documentation using the named +generator+ ("darkfish" or "ri")
+ # and following the given +options+.
+ #
+ # Documentation will be generated into +destination+
+
+ def document generator, options, destination
+ options = options.dup
+ options.exclude ||= [] # TODO maybe move to RDoc::Options#finish
+ options.setup_generator generator
+ options.op_dir = destination
+ options.finish
+
+ @rdoc.options = options
+ @rdoc.generator = options.generator.new options
+
+ say "Installing #{generator} documentation for #{@spec.full_name}"
+
+ FileUtils.mkdir_p options.op_dir
+
+ Dir.chdir options.op_dir do
+ begin
+ @rdoc.class.current = @rdoc
+ @rdoc.generator.generate @file_info
+ ensure
+ @rdoc.class.current = nil
+ end
+ end
+ end
+
+ ##
+ # Generates RDoc and ri data
+
+ def generate
+ return unless @generate_ri or @generate_rdoc
+
+ setup
+
+ ::RDoc::RDoc.reset
+
+ options = ::RDoc::Options.new
+ options.default_title = "#{@spec.full_name} Documentation"
+ options.files = []
+ options.files.push(*@spec.require_paths)
+ options.files.push(*@spec.extra_rdoc_files)
+
+ args = @spec.rdoc_options
+
+ case config_args = Gem.configuration[:rdoc]
+ when String then
+ args = args.concat config_args.split
+ when Array then
+ args = args.concat config_args
+ end
+
+ delete_legacy_args args
+ options.parse args
+ options.quiet = !Gem.configuration.really_verbose
+
+ @rdoc = new_rdoc
+ @rdoc.options = options
+
+ Dir.chdir @spec.full_gem_path do
+ @file_info = @rdoc.parse_files options.files
+ end
+
+ document 'ri', options, @ri_dir if
+ @generate_ri and (@force or not File.exist? @ri_dir)
+
+ document 'darkfish', options, @rdoc_dir if
+ @generate_rdoc and (@force or not File.exist? @rdoc_dir)
+ end
+
+ ##
+ # #new_rdoc creates a new RDoc instance. This method is provided only to
+ # make testing easier.
+
+ def new_rdoc # :nodoc:
+ ::RDoc::RDoc.new
+ end
+
+ ##
+ # Is rdoc documentation installed?
+
+ def rdoc_installed?
+ File.exist? @rdoc_dir
+ end
+
+ ##
+ # Removes generated RDoc and ri data
+
+ def remove
+ base_dir = @spec.base_dir
+
+ raise Gem::FilePermissionError, base_dir unless File.writable? base_dir
+
+ FileUtils.rm_rf @rdoc_dir
+ FileUtils.rm_rf @ri_dir
+ end
+
+ ##
+ # Is ri data installed?
+
+ def ri_installed?
+ File.exist? @ri_dir
+ end
+
+ ##
+ # Prepares the spec for documentation generation
+
+ def setup
+ self.class.load_rdoc
+
+ raise Gem::FilePermissionError, @doc_dir if
+ File.exist?(@doc_dir) and not File.writable?(@doc_dir)
+
+ FileUtils.mkdir_p @doc_dir unless File.exist? @doc_dir
+ end
+
+end
+
diff --git a/lib/rdoc/text.rb b/lib/rdoc/text.rb
index ace44bf56f..aec334b545 100644
--- a/lib/rdoc/text.rb
+++ b/lib/rdoc/text.rb
@@ -157,7 +157,7 @@ http://rubyforge.org/tracker/?atid=2472&group_id=627&func=browse
def strip_stars text
encoding = text.encoding if Object.const_defined? :Encoding
- text = text.gsub %r%Document-method:\s+[\w:.#]+%, ''
+ text = text.gsub %r%Document-method:\s+[\w:.#=!?]+%, ''
space = ' '
space.force_encoding encoding if encoding
diff --git a/lib/rdoc/top_level.rb b/lib/rdoc/top_level.rb
index d0ea621f8c..b9fd5c9f6f 100644
--- a/lib/rdoc/top_level.rb
+++ b/lib/rdoc/top_level.rb
@@ -220,6 +220,20 @@ class RDoc::TopLevel < RDoc::Context
end
##
+ # Creates a new RDoc::TopLevel with +file_name+ only if one with the same
+ # name does not exist in all_files.
+
+ def self.new file_name
+ if top_level = @all_files_hash[file_name] then
+ top_level
+ else
+ top_level = super
+ @all_files_hash[file_name] = top_level
+ top_level
+ end
+ end
+
+ ##
# Removes from +all_hash+ the contexts that are nodoc or have no content.
#
# See RDoc::Context#remove_from_documentation?
@@ -296,6 +310,15 @@ class RDoc::TopLevel < RDoc::Context
end
##
+ # An RDoc::TopLevel is equal to another with the same absolute_name
+
+ def == other
+ other.class === self and @absolute_name == other.absolute_name
+ end
+
+ alias eql? ==
+
+ ##
# Adds +an_alias+ to +Object+ instead of +self+.
def add_alias(an_alias)
@@ -376,6 +399,14 @@ class RDoc::TopLevel < RDoc::Context
end
##
+ # An RDoc::TopLevel has the same hash as another with the same
+ # absolute_name
+
+ def hash
+ @absolute_name.hash
+ end
+
+ ##
# URL for this with a +prefix+
def http_url(prefix)