Permalink
Browse files

Import various improvements from Thierry Lambert. See History.txt.

Improve RDoc::Parser::binary? where Encoding is available.
  • Loading branch information...
1 parent e4f312e commit 54dbcf70b60f17652650d09d081108887b5399f6 @drbrain drbrain committed Sep 10, 2010
Showing with 3,671 additions and 2,275 deletions.
  1. +1 −0 .document
  2. +36 −4 History.txt
  3. +2 −0 Manifest.txt
  4. +9 −3 README.txt
  5. +12 −293 lib/rdoc.rb
  6. +65 −14 lib/rdoc/alias.rb
  7. +22 −151 lib/rdoc/any_method.rb
  8. +32 −117 lib/rdoc/attr.rb
  9. +136 −18 lib/rdoc/class_module.rb
  10. +52 −29 lib/rdoc/code_object.rb
  11. +29 −4 lib/rdoc/constant.rb
  12. +455 −230 lib/rdoc/context.rb
  13. +0 −1 lib/rdoc/generator/darkfish.rb
  14. +57 −24 lib/rdoc/generator/markup.rb
  15. +1 −1 lib/rdoc/generator/template/darkfish/classpage.rhtml
  16. +5 −1 lib/rdoc/include.rb
  17. +464 −2 lib/rdoc/markup.rb
  18. +1 −2 lib/rdoc/markup/attribute_manager.rb
  19. +5 −3 lib/rdoc/markup/blank_line.rb
  20. +144 −3 lib/rdoc/markup/formatter_test_case.rb
  21. +2 −1 lib/rdoc/markup/inline.rb
  22. +189 −236 lib/rdoc/markup/parser.rb
  23. +29 −6 lib/rdoc/markup/preprocess.rb
  24. +1 −0 lib/rdoc/markup/raw.rb
  25. +2 −2 lib/rdoc/markup/to_ansi.rb
  26. +5 −2 lib/rdoc/markup/to_bs.rb
  27. +135 −82 lib/rdoc/markup/to_html.rb
  28. +77 −26 lib/rdoc/markup/to_html_crossref.rb
  29. +17 −48 lib/rdoc/markup/to_rdoc.rb
  30. +5 −1 lib/rdoc/markup/to_test.rb
  31. +3 −3 lib/rdoc/markup/verbatim.rb
  32. +269 −0 lib/rdoc/method_attr.rb
  33. +11 −2 lib/rdoc/normal_class.rb
  34. +0 −5 lib/rdoc/normal_module.rb
  35. +166 −28 lib/rdoc/options.rb
  36. +27 −16 lib/rdoc/parser.rb
  37. +54 −11 lib/rdoc/parser/c.rb
  38. +54 −48 lib/rdoc/parser/ruby.rb
  39. +1 −2 lib/rdoc/parser/simple.rb
  40. +17 −18 lib/rdoc/rdoc.rb
  41. +19 −0 lib/rdoc/require.rb
  42. +14 −7 lib/rdoc/ri/driver.rb
  43. +1 −1 lib/rdoc/ri/store.rb
  44. +1 −1 lib/rdoc/ruby_lex.rb
  45. +2 −1 lib/rdoc/single_class.rb
  46. +43 −59 lib/rdoc/stats.rb
  47. +3 −4 lib/rdoc/text.rb
  48. +280 −39 lib/rdoc/top_level.rb
  49. +41 −7 test/test_attribute_manager.rb
  50. +2 −2 test/test_rdoc_any_method.rb
  51. +15 −8 test/test_rdoc_attr.rb
  52. +45 −5 test/test_rdoc_code_object.rb
  53. +6 −26 test/test_rdoc_context.rb
  54. +5 −1 test/test_rdoc_generator_darkfish.rb
  55. +3 −1 test/test_rdoc_generator_ri.rb
  56. +1 −0 test/test_rdoc_include.rb
  57. +106 −95 test/test_rdoc_markup_parser.rb
  58. +4 −0 test/test_rdoc_markup_pre_process.rb
  59. +43 −153 test/test_rdoc_markup_to_ansi.rb
  60. +42 −156 test/test_rdoc_markup_to_bs.rb
  61. +106 −41 test/test_rdoc_markup_to_html.rb
  62. +10 −10 test/test_rdoc_markup_to_html_crossref.rb
  63. +40 −151 test/test_rdoc_markup_to_rdoc.rb
  64. +1 −1 test/test_rdoc_normal_class.rb
  65. +6 −1 test/test_rdoc_normal_module.rb
  66. +30 −3 test/test_rdoc_options.rb
  67. +2 −2 test/test_rdoc_parser.rb
  68. +42 −1 test/test_rdoc_parser_c.rb
  69. +92 −19 test/test_rdoc_parser_ruby.rb
  70. +25 −1 test/test_rdoc_parser_simple.rb
  71. +15 −5 test/test_rdoc_rdoc.rb
  72. +21 −21 test/test_rdoc_ri_driver.rb
  73. +3 −3 test/test_rdoc_ri_store.rb
  74. +1 −1 test/test_rdoc_task.rb
  75. +7 −8 test/test_rdoc_text.rb
  76. +2 −4 test/test_rdoc_top_level.rb
View
1 .document
@@ -1,4 +1,5 @@
History.txt
+LICENSE.txt
README.txt
RI.txt
lib
View
40 History.txt
@@ -1,12 +1,44 @@
=== 2.6
* Major enhancements
- * Removed TimeConstantMethods
+ * Improved merging of classes and modules across multiple files including
+ more accurate documentation statistics. Patch by Thierry Lambert.
+ * Improved handling of method aliases. Patch by Thierry Lambert.
+ * Added support for class aliases. Patch by Thierry Lambert.
+ * Improved handling of visibility of RDoc code objects. Patch by Thierry
+ Lambert.
* RDoc now converts input files to a single encoding specified by
- --encoding. See RDoc::RDoc and RDoc::Options#encoding.
- * Added --encoding which is preferred over --charset
+ <tt>--encoding</tt>. See RDoc::RDoc and RDoc::Options#encoding.
+ <tt>--encoding</tt> is now preferred over <tt>--charset</tt>
+ * RDoc::Attr#type is now RDoc::Attr#definition. Patch by Thierry Lambert.
+ * Removed TimeConstantMethods
* Minor enhancements
- * Added --dry-run
+ * Added rdoc argument <tt>--dry-run</tt>
+ * Added rdoc arguments <tt>--all</tt>, <tt>--visibility</tt>,
+ <tt>--force-output</tt>, <tt>--hyperlink-all</tt>,
+ <tt>--line-numbers</tt>, <tt>--style</tt>. Patch by Thierry Lambert.
+ * RDoc::Markup::FormatterTestCase has been expanded. Patch by Thierry
+ Lambert.
+ * RDoc::Markup::TextFormatterTestCase has been extracted from RDoc tests.
+ Patch by Thierry Lambert.
+ * Various RDoc::Markup::Parser enhancements. Patch by Thierry Lambert.
+ * RDoc::Parser::binary? is more robust now that it uses Encoding.
+ * Deprecated rdoc arguments are now explicitly mentioned in rdoc command
+ output. Patch by Thierry Lambert.
+ * Constant values are formatted more accurately. Patch by Thierry Lambert.
+ * Enhanced call-seq parsing in RDoc::Parser::C. Patch by Thierry Lambert.
+ * RDoc no longer uses kw, cmt, re or str classes for embedded source code
+ snippets. Patch by Thierry Lambert.
+ * RDoc directives may now be escaped with a leading '\\'. Patch by Thierry
+ Lambert.
+ * RDoc note lists (<tt>label::</tt>) now generate a table with class
+ rdoc-list. Patch by Thierry Lambert.
+ * RDoc markup documentation has been moved to RDoc::Markup including notes
+ on how to document source code.
+ * An RDoc::Require is now always listed at the file level. Patch by Thierry
+ Lambert.
+* Bug fixes
+ * RDoc::Generator tests no longer require installed RDoc on Ruby 1.9
=== 2.5.11 / 2010-08-20
View
2 Manifest.txt
@@ -70,6 +70,7 @@ lib/rdoc/markup/parser.rb
lib/rdoc/markup/preprocess.rb
lib/rdoc/markup/raw.rb
lib/rdoc/markup/rule.rb
+lib/rdoc/markup/text_formatter_test_case.rb
lib/rdoc/markup/to_ansi.rb
lib/rdoc/markup/to_bs.rb
lib/rdoc/markup/to_html.rb
@@ -78,6 +79,7 @@ lib/rdoc/markup/to_rdoc.rb
lib/rdoc/markup/to_test.rb
lib/rdoc/markup/verbatim.rb
lib/rdoc/meta_method.rb
+lib/rdoc/method_attr.rb
lib/rdoc/normal_class.rb
lib/rdoc/normal_module.rb
lib/rdoc/options.rb
View
12 README.txt
@@ -1,4 +1,4 @@
-= \RDoc
+= \RDoc - Ruby Documentation System
* {RDoc Project Page}[http://rubyforge.org/projects/rdoc/]
* {RDoc Documentation}[http://rdoc.rubyforge.org/]
@@ -25,13 +25,19 @@ See RDoc for a description of RDoc's markup and basic use.
== BUGS:
If you find a bug, please report it at the RDoc project's
-tracker[http://rubyforge.org/tracker/?group_id=627] on RubyForge:
+tracker[http://rubyforge.org/tracker/?group_id=627] on RubyForge
== LICENSE:
RDoc is Copyright (c) 2001-2003 Dave Thomas, The Pragmatic Programmers.
-Portions (c) 2007-2009 Eric Hodel. Portions copyright others, see individual
+Portions (c) 2007-2010 Eric Hodel. Portions copyright others, see individual
files for details.
It is free software, and may be redistributed under the terms specified in
LICENSE.txt.
+
+== WARRANTY:
+
+This software is provided "as is" and without any express or implied
+warranties, including, without limitation, the implied warranties of
+merchantibility and fitness for a particular purpose.
View
305 lib/rdoc.rb
@@ -18,14 +18,15 @@
# == Roadmap
#
# * If you want to use RDoc to create documentation for your Ruby source files,
-# read on.
+# read the summary below, and refer to <tt>rdoc --help</tt> for command line
+# usage, and RDoc::Markup for a detailed description of RDoc's markup.
# * If you want to generate documentation for extensions written in C, see
# RDoc::Parser::C
# * If you want to drive RDoc programmatically, see RDoc::RDoc.
-# * If you want to use the library to format text blocks into HTML, have a look
-# at RDoc::Markup.
+# * If you want to use the library to format text blocks into HTML, look at
+# RDoc::Markup.
# * If you want to try writing your own HTML output template, see
-# RDoc::Generator::Darkfish
+# RDoc::Generator::Darkfish.
#
# == Summary
#
@@ -50,7 +51,7 @@
# index page contain the documentation for the primary file. In our
# case, we could type
#
-# % rdoc --main rdoc.rb
+# % rdoc --main README.txt
#
# You'll find information on the various formatting tricks you can use
# in comment blocks in the documentation this generates.
@@ -62,281 +63,9 @@
# markers). If directory names are passed to RDoc, they are scanned
# recursively for C and Ruby source files only.
#
-# == \Options
-#
-# rdoc can be passed a variety of command-line options. In addition,
-# options can be specified via the +RDOCOPT+ environment variable, which
-# functions similarly to the +RUBYOPT+ environment variable.
-#
-# % export RDOCOPT="-S"
-#
-# will make rdoc default to inline method source code. Command-line options
-# always will override those in +RDOCOPT+.
-#
-# Run:
-#
-# rdoc --help
-#
-# for full details on rdoc's options.
-#
-# == Documenting Source Code
-#
-# Comment blocks can be written fairly naturally, either using <tt>#</tt> on
-# successive lines of the comment, or by including the comment in
-# a =begin/=end block. If you use the latter form, the =begin line must be
-# flagged with an RDoc tag:
-#
-# =begin rdoc
-# Documentation to be processed by RDoc.
-#
-# ...
-# =end
-#
-# RDoc stops processing comments if it finds a comment line containing
-# a <tt>--</tt>. This can be used to separate external from internal
-# comments, or to stop a comment being associated with a method, class, or
-# module. Commenting can be turned back on with a line that starts with a
-# <tt>++</tt>.
-#
-# ##
-# # Extract the age and calculate the date-of-birth.
-# #--
-# # FIXME: fails if the birthday falls on February 29th
-# #++
-# # The DOB is returned as a Time object.
-#
-# def get_dob(person)
-# # ...
-# end
-#
-# Names of classes, files, and any method names containing an
-# underscore or preceded by a hash character are automatically hyperlinked
-# from comment text to their description.
-#
-# Method parameter lists are extracted and displayed with the method
-# description. If a method calls +yield+, then the parameters passed to yield
-# will also be displayed:
-#
-# def fred
-# ...
-# yield line, address
-#
-# This will get documented as:
-#
-# fred() { |line, address| ... }
-#
-# You can override this using a comment containing ':yields: ...' immediately
-# after the method definition
-#
-# def fred # :yields: index, position
-# # ...
-#
-# yield line, address
-#
-# which will get documented as
-#
-# fred() { |index, position| ... }
-#
-# +:yields:+ is an example of a documentation directive. These appear
-# immediately after the start of the document element they are modifying.
-#
-# RDoc automatically cross-references words with underscores or camel-case.
-# To suppress cross-references, prefix the word with a \\ character. To
-# include special characters like "\\n", you'll need to use two \\
-# characters like "\\\\\\n".
-#
-# == \Markup
-#
-# * The markup engine looks for a document's natural left margin. This is
-# used as the initial margin for the document.
-#
-# * Consecutive lines starting at this margin are considered to be a
-# paragraph.
-#
-# * If a paragraph starts with a "*", "-", or with "<digit>.", then it is
-# taken to be the start of a list. The margin in increased to be the first
-# non-space following the list start flag. Subsequent lines should be
-# indented to this new margin until the list ends. For example:
-#
-# * this is a list with three paragraphs in
-# the first item. This is the first paragraph.
-#
-# And this is the second paragraph.
-#
-# 1. This is an indented, numbered list.
-# 2. This is the second item in that list
-#
-# This is the third conventional paragraph in the
-# first list item.
-#
-# * This is the second item in the original list
-#
-# * You can also construct labeled lists, sometimes called description
-# or definition lists. Do this by putting the label in square brackets
-# and indenting the list body:
-#
-# [cat] a small furry mammal
-# that seems to sleep a lot
-#
-# [ant] a little insect that is known
-# to enjoy picnics
-#
-# A minor variation on labeled lists uses two colons to separate the
-# label from the list body:
-#
-# cat:: a small furry mammal
-# that seems to sleep a lot
-#
-# ant:: a little insect that is known
-# to enjoy picnics
-#
-# This latter style guarantees that the list bodies' left margins are
-# aligned: think of them as a two column table.
-#
-# * Any line that starts to the right of the current margin is treated
-# as verbatim text. This is useful for code listings. The example of a
-# list above is also verbatim text.
-#
-# * A line starting with an equals sign (=) is treated as a
-# heading. Level one headings have one equals sign, level two headings
-# have two,and so on.
-#
-# * A line starting with three or more hyphens (at the current indent)
-# generates a horizontal rule. The more hyphens, the thicker the rule
-# (within reason, and if supported by the output device)
-#
-# * You can use markup within text (except verbatim) to change the
-# appearance of parts of that text. Out of the box, RDoc::Markup
-# supports word-based and general markup.
-#
-# Word-based markup uses flag characters around individual words:
-#
-# [<tt>\*word*</tt>] displays word in a *bold* font
-# [<tt>\_word_</tt>] displays word in an _emphasized_ font
-# [<tt>\+word+</tt>] displays word in a +code+ font
-#
-# General markup affects text between a start delimiter and and end
-# delimiter. Not surprisingly, these delimiters look like HTML markup.
-#
-# [<tt>\<b>text...</b></tt>] displays word in a *bold* font
-# [<tt>\<em>text...</em></tt>] displays word in an _emphasized_ font
-# [<tt>\<i>text...</i></tt>] displays word in an <i>italicized</i> font
-# [<tt>\<tt>text...\</tt></tt>] displays word in a +code+ font
-#
-# Unlike conventional Wiki markup, general markup can cross line
-# boundaries. You can turn off the interpretation of markup by
-# preceding the first character with a backslash. This only works for
-# simple markup, not HTML-style markup.
-#
-# * Hyperlinks to the web starting http:, mailto:, ftp:, or www. are
-# recognized. An HTTP url that references an external image file is
-# converted into an inline \<IMG..>. Hyperlinks starting 'link:' are
-# assumed to refer to local files whose path is relative to the --op
-# directory.
-#
-# Hyperlinks can also be of the form <tt>label</tt>[url], in which
-# case the label is used in the displayed text, and +url+ is
-# used as the target. If +label+ contains multiple words,
-# put it in braces: <em>{multi word label}[</em>url<em>]</em>.
-#
-# Example hyperlinks:
-#
-# link:RDoc.html
-# http://rdoc.rubyforge.org
-# mailto:user@example.com
-# {RDoc Documentation}[http://rdoc.rubyforge.org]
-# {RDoc Markup}[link:RDoc/Markup.html]
-#
-# == Directives
-#
-# [+:nodoc:+ / +:nodoc:+ all]
-# This directive prevents documentation for the element from
-# being generated. For classes and modules, the methods, aliases,
-# constants, and attributes directly within the affected class or
-# module also will be omitted. By default, though, modules and
-# classes within that class of module _will_ be documented. This is
-# turned off by adding the +all+ modifier.
-#
-# module MyModule # :nodoc:
-# class Input
-# end
-# end
-#
-# module OtherModule # :nodoc: all
-# class Output
-# end
-# end
-#
-# In the above code, only class <tt>MyModule::Input</tt> will be documented.
-# The +:nodoc:+ directive is global across all files for the class or module
-# to which it applies, so use +:stopdoc:+/+:startdoc:+ to suppress
-# documentation only for a particular set of methods, etc.
-#
-# [+:doc:+]
-# Forces a method or attribute to be documented even if it wouldn't be
-# otherwise. Useful if, for example, you want to include documentation of a
-# particular private method.
-#
-# [+:notnew:+]
-# Only applicable to the +initialize+ instance method. Normally RDoc
-# assumes that the documentation and parameters for +initialize+ are
-# actually for the +new+ method, and so fakes out a +new+ for the class.
-# The +:notnew:+ modifier stops this. Remember that +initialize+ is private,
-# so you won't see the documentation unless you use the +-a+ command line
-# option.
-#
-# Comment blocks can contain other directives:
-#
-# [<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. 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:
-#
-# # ----------------------------------------
-# # :section: My Section
-# # This is the section that I wrote.
-# # See it glisten in the noon-day sun.
-# # ----------------------------------------
-#
-# [+:call-seq:+]
-# Lines up to the next blank line in the comment are treated as the method's
-# calling sequence, overriding the default parsing of method parameters and
-# yield arguments.
-#
-# [+:include:+ _filename_]
-# \Include the contents of the named file at this point. The file will be
-# searched for in the directories listed by the +--include+ option, or in
-# the current directory by default. The contents of the file will be
-# shifted to have the same indentation as the ':' at the start of
-# the :include: directive.
-#
-# [+:title:+ _text_]
-# Sets the title for the document. Equivalent to the <tt>--title</tt>
-# command line parameter. (The command line parameter overrides any :title:
-# directive in the source).
-#
-# [+:enddoc:+]
-# Document nothing further at the current level.
-#
-# [+:main:+ _name_]
-# Equivalent to the <tt>--main</tt> command line parameter.
-#
-# [+:stopdoc:+ / +:startdoc:+]
-# Stop and start adding new documentation elements to the current container.
-# For example, if a class has a number of constants that you don't want to
-# document, put a +:stopdoc:+ before the first, and a +:startdoc:+ after the
-# last. If you don't specify a +:startdoc:+ by the end of the container,
-# disables documentation for the entire class or module.
-#
-# Further directives can be found in RDoc::Parser::Ruby and RDoc::Parser::C
-#
# == Other stuff
#
-# RDoc is currently being maintained by Eric Hodel <drbrain@segment7.net>
+# RDoc is currently being maintained by Eric Hodel <drbrain@segment7.net>.
#
# Dave Thomas <dave@pragmaticprogrammer.com> is the original author of RDoc.
#
@@ -345,24 +74,9 @@
# * The Ruby parser in rdoc/parse.rb is based heavily on the outstanding
# work of Keiju ISHITSUKA of Nippon Rational Inc, who produced the Ruby
# parser for irb and the rtags package.
-#
# * Charset patch from MoonWolf.
-#
# * Rich Kilmer wrote the kilmer.rb output template.
-#
# * Dan Brickley led the design of the RDF format.
-#
-# == License
-#
-# RDoc is Copyright (c) 2001-2003 Dave Thomas, The Pragmatic Programmers. It
-# is free software, and may be redistributed under the terms specified
-# in the README file of the Ruby distribution.
-#
-# == Warranty
-#
-# This software is provided "as is" and without any express or implied
-# warranties, including, without limitation, the implied warranties of
-# merchantibility and fitness for a particular purpose.
module RDoc
@@ -386,6 +100,11 @@ def self.const_missing const_name # :nodoc:
VERSION = '2.6'
##
+ # Method visibilities
+
+ VISIBILITIES = [:public, :protected, :private]
+
+ ##
# Name of the dotfile that contains the description of files to be processed
# in the current directory
View
79 lib/rdoc/alias.rb
@@ -3,47 +3,75 @@
##
# Represent an alias, which is an old_name/new_name pair associated with a
# particular context
+#--
+# TODO implement Alias as a proxy to a method/attribute, inheriting from
+# MethodAttr
class RDoc::Alias < RDoc::CodeObject
##
- # Allow comments to be overridden
+ # Aliased method's name
- attr_writer :comment
+ attr_reader :new_name
- ##
- # Aliased name
-
- attr_accessor :new_name
+ alias name new_name
##
- # Aliasee's name
+ # Aliasee method's name
- attr_accessor :old_name
+ attr_reader :old_name
##
- # Is this a singeton alias?
+ # Is this an alias declared in a singleton context?
attr_accessor :singleton
##
# Source file token stream
- attr_accessor :text
+ attr_reader :text
##
# Creates a new Alias with a token stream of +text+ that aliases +old_name+
- # to +new_name+ and has +comment+
+ # to +new_name+, has +comment+ and is a +singleton+ context.
- def initialize(text, old_name, new_name, comment)
+ def initialize(text, old_name, new_name, comment, singleton = false)
super()
@text = text
+ @singleton = singleton
@old_name = old_name
@new_name = new_name
self.comment = comment
+ end
+
+ ##
+ # Order by #singleton then #new_name
+
+ def <=>(other)
+ [@singleton ? 0 : 1, new_name] <=> [other.singleton ? 0 : 1, other.new_name]
+ end
+
+ ##
+ # HTML fragment reference for this alias
+
+ def aref
+ type = singleton ? 'c' : 'i'
+ "#alias-#{type}-#{html_name}"
+ end
+
+ ##
+ # Full old name including namespace
+
+ def full_old_name
+ @full_name || "#{parent.name}#{pretty_old_name}"
+ end
- @singleton = false
+ ##
+ # HTML id-friendly version of +#new_name+.
+
+ def html_name
+ CGI.escape(@new_name.gsub('-', '-2D')).gsub('%','-').sub(/^-/, '')
end
def inspect # :nodoc:
@@ -54,8 +82,31 @@ def inspect # :nodoc:
]
end
+ ##
+ # '::' for the alias of a singleton method/attribute, '#' for instance-level.
+
+ def name_prefix
+ singleton ? '::' : '#'
+ end
+
+ ##
+ # Old name with prefix '::' or '#'.
+
+ def pretty_old_name
+ "#{singleton ? '::' : '#'}#{@old_name}"
+ end
+
+ ##
+ # New name with prefix '::' or '#'.
+
+ def pretty_new_name
+ "#{singleton ? '::' : '#'}#{@new_name}"
+ end
+
+ alias pretty_name pretty_new_name
+
def to_s # :nodoc:
- "alias: #{self.old_name} -> #{self.new_name}\n#{self.comment}"
+ "alias: #{self.new_name} -> #{self.pretty_old_name} in: #{parent}"
end
end
View
173 lib/rdoc/any_method.rb
@@ -1,106 +1,56 @@
-require 'rdoc/code_object'
+require 'rdoc/method_attr'
require 'rdoc/tokenstream'
##
# AnyMethod is the base class for objects representing methods
-class RDoc::AnyMethod < RDoc::CodeObject
+class RDoc::AnyMethod < RDoc::MethodAttr
- MARSHAL_VERSION = 1 # :nodoc:
-
- include Comparable
-
- ##
- # Method name
-
- attr_writer :name
-
- ##
- # public, protected, private
-
- attr_accessor :visibility
-
- ##
- # Parameters yielded by the called block
-
- attr_accessor :block_params
+ MARSHAL_VERSION = 0 # :nodoc:
##
# Don't rename \#initialize to \::new
attr_accessor :dont_rename_initialize
##
- # Is this a singleton method?
-
- attr_accessor :singleton
-
- ##
- # Source file token stream
-
- attr_reader :text
-
- ##
- # Array of other names for this method
-
- attr_reader :aliases
-
- ##
- # The method we're aliasing
+ # Different ways to call this method
- attr_accessor :is_alias_for
+ attr_accessor :call_seq
##
# Parameters for this method
attr_accessor :params
- ##
- # Different ways to call this method
-
- attr_accessor :call_seq
-
include RDoc::TokenStream
def initialize(text, name)
- super()
-
- @text = text
- @name = name
-
- @aliases = []
- @block_params = nil
- @call_seq = nil
+ super text, name
@dont_rename_initialize = false
- @is_alias_for = nil
- @params = nil
- @parent_name = nil
- @singleton = nil
@token_stream = nil
- @visibility = :public
end
##
- # Order by #singleton then #name
+ # Adds +an_alias+ as an alias for this method in +context+.
- def <=>(other)
- [@singleton ? 0 : 1, @name] <=> [other.singleton ? 0 : 1, other.name]
- end
-
- ##
- # Adds +method+ as an alias for this method
-
- def add_alias(method)
+ def add_alias(an_alias, context)
+ method = self.class.new an_alias.text, an_alias.new_name
+ method.singleton = self.singleton
+ method.params = self.params
+ method.visibility = self.visibility
+ method.comment = an_alias.comment
+ method.is_alias_for = self
@aliases << method
+ context.add_method method
+ method
end
##
- # HTML fragment reference for this method
-
- def aref
- type = singleton ? 'c' : 'i'
+ # Prefix for +aref+ is 'method'.
- "method-#{type}-#{CGI.escape name}"
+ def aref_prefix
+ 'method'
end
##
@@ -117,30 +67,6 @@ def arglists
end
##
- # HTML id-friendly method name
-
- def html_name
- @name.gsub(/[^a-z]+/, '-')
- end
-
- def inspect # :nodoc:
- alias_for = @is_alias_for ? " (alias for #{@is_alias_for.name})" : nil
- "#<%s:0x%x %s (%s)%s>" % [
- self.class, object_id,
- full_name,
- visibility,
- alias_for,
- ]
- end
-
- ##
- # Full method name including namespace
-
- def full_name
- @full_name ||= "#{@parent ? @parent.full_name : '(unknown)'}#{pretty_name}"
- end
-
- ##
# Dumps this AnyMethod for use by ri. See also #marshal_load
def marshal_dump
@@ -192,12 +118,14 @@ def marshal_load(array)
end
array[8].each do |new_name, comment|
- add_alias RDoc::Alias.new(nil, @name, new_name, comment)
+ add_alias RDoc::Alias.new(nil, @name, new_name, comment, @singleton)
end
end
##
# Method name
+ #
+ # If the method has no assigned name, it extracts it from #call_seq.
def name
return @name if @name
@@ -229,62 +157,5 @@ def param_seq
params
end
- ##
- # Name of our parent with special handling for un-marshaled methods
-
- def parent_name
- @parent_name || super
- end
-
- ##
- # Path to this method
-
- def path
- "#{@parent.path}##{aref}"
- end
-
- ##
- # Method name with class/instance indicator
-
- def pretty_name
- "#{singleton ? '::' : '#'}#{@name}"
- end
-
- def pretty_print q # :nodoc:
- alias_for = @is_alias_for ? "alias for #{@is_alias_for.name}" : nil
-
- q.group 2, "[#{self.class.name} #{full_name} #{visibility}", "]" do
- if alias_for then
- q.breakable
- q.text alias_for
- end
-
- if text then
- q.breakable
- q.text "text:"
- q.breakable
- q.pp @text
- end
-
- unless comment.empty? then
- q.breakable
- q.text "comment:"
- q.breakable
- q.pp @comment
- end
- end
- end
-
- def to_s # :nodoc:
- "#{self.class.name}: #{full_name} (#{@text})\n#{@comment}"
- end
-
- ##
- # Type of method (class or instance)
-
- def type
- singleton ? 'class' : 'instance'
- end
-
end
View
149 lib/rdoc/attr.rb
@@ -1,113 +1,65 @@
-require 'rdoc/code_object'
+require 'rdoc/method_attr'
##
# An attribute created by \#attr, \#attr_reader, \#attr_writer or
# \#attr_accessor
-class RDoc::Attr < RDoc::CodeObject
+class RDoc::Attr < RDoc::MethodAttr
- MARSHAL_VERSION = 0 # :nodoc:
-
- ##
- # Name of the attribute
-
- attr_accessor :name
+ MARSHAL_VERSION = 1 # :nodoc:
##
# Is the attribute readable, writable or both?
attr_accessor :rw
- ##
- # Source file token stream
-
- attr_accessor :text
-
- ##
- # public, protected, private
-
- attr_accessor :visibility
+ def initialize(text, name, rw, comment, singleton = false)
+ super text, name
- def initialize(text, name, rw, comment)
- super()
- @text = text
- @name = name
@rw = rw
- @visibility = :public
+ @singleton = singleton
self.comment = comment
end
##
- # Attributes are ordered by name
-
- def <=>(other)
- self.name <=> other.name
- end
-
- ##
- # Attributes are equal when their names and rw is identical
+ # Attributes are equal when their names, singleton and rw are identical
def == other
self.class == other.class and
self.name == other.name and
- self.rw == other.rw
+ self.rw == other.rw and
+ self.singleton == other.singleton
end
##
- # HTML fragment reference for this attr
+ # Add +an_alias+ as an attribute in +context+.
- def aref
- type = singleton ? 'c' : 'i'
-
- "attribute-#{type}-#{CGI.escape name}"
+ def add_alias(an_alias, context)
+ new_attr = self.class.new(self.text, an_alias.new_name, self.rw,
+ self.comment, self.singleton)
+ new_attr.visibility = self.visibility
+ new_attr.is_alias_for = self
+ @aliases << new_attr
+ context.add_attribute new_attr
+ new_attr
end
##
- # Returns nil, for duck typing with RDoc::AnyMethod
+ # The #aref prefix for attributes
- def arglists
+ def aref_prefix
+ 'attribute'
end
##
- # Returns nil, for duck typing with RDoc::AnyMethod
-
- def block_params
- end
+ # Returns attr_reader, attr_writer or attr_accessor as appropriate.
- ##
- # Returns nil, for duck typing with RDoc::AnyMethod
-
- def call_seq
- end
-
- ##
- # Partially bogus as Attr has no parent. For duck typing with
- # RDoc::AnyMethod.
-
- def full_name
- @full_name ||= "#{@parent ? @parent.full_name : '(unknown)'}##{name}"
- end
-
- ##
- # An HTML id-friendly representation of #name
-
- def html_name
- @name.gsub(/[^a-z]+/, '-')
- end
-
- def inspect # :nodoc:
- attr = case rw
- when 'RW' then :attr_accessor
- when 'R' then :attr_reader
- when 'W' then :attr_writer
- else
- " (#{rw})"
- end
-
- "#<%s:0x%x %s.%s :%s>" % [
- self.class, object_id,
- parent_name, attr, @name,
- ]
+ def definition
+ case @rw
+ when 'RW' then 'attr_accessor'
+ when 'R' then 'attr_reader'
+ when 'W' then 'attr_writer'
+ end
end
##
@@ -120,11 +72,12 @@ def marshal_dump
@rw,
@visibility,
parse(@comment),
+ singleton,
]
end
##
- # Loads this AnyMethod from +array+. For a loaded AnyMethod the following
+ # Loads this Attr from +array+. For a loaded Attr the following
# methods will return cached values:
#
# * #full_name
@@ -136,51 +89,13 @@ def marshal_load array
@rw = array[3]
@visibility = array[4]
@comment = array[5]
+ @singleton = array[6] || false # MARSHAL_VERSION == 0
@parent_name = @full_name
end
- ##
- # Name of our parent with special handling for un-marshaled methods
-
- def parent_name
- @parent_name || super
- end
-
- ##
- # For duck typing with RDoc::AnyMethod, returns nil
-
- def params
- nil
- end
-
- ##
- # URL path for this attribute
-
- def path
- "#{@parent.path}##{@name}"
- end
-
- ##
- # For duck typing with RDoc::AnyMethod
-
- def singleton
- false
- end
-
def to_s # :nodoc:
- "#{type} #{name}\n#{comment}"
- end
-
- ##
- # Returns attr_reader, attr_writer or attr_accessor as appropriate
-
- def type
- case @rw
- when 'RW' then 'attr_accessor'
- when 'R' then 'attr_reader'
- when 'W' then 'attr_writer'
- end
+ "#{definition} #{name} in: #{parent}"
end
end
View
154 lib/rdoc/class_module.rb
@@ -8,31 +8,102 @@ class RDoc::ClassModule < RDoc::Context
MARSHAL_VERSION = 0 # :nodoc:
- attr_accessor :diagram
+ ##
+ # Constants that are aliases for this class or module
+
+ attr_accessor :constant_aliases
+
+ attr_accessor :diagram # :nodoc:
##
- # Creates a new ClassModule with +name+ with optional +superclass+
+ # Class or module this constant is an alias for
- def initialize(name, superclass = 'Object')
- @diagram = nil
- @full_name = nil
- @name = name
- @superclass = superclass
+ attr_accessor :is_alias_for
+
+ ##
+ # Return a RDoc::ClassModule of class +class_type+ that is a copy
+ # of module +module+. Used to promote modules to classes.
+
+ 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
+
+ klass.attributes.concat mod.attributes
+ klass.method_list.concat mod.method_list
+ klass.aliases.concat mod.aliases
+ klass.external_aliases.concat mod.external_aliases
+ klass.constants.concat mod.constants
+ klass.includes.concat mod.includes
+
+ klass.methods_hash.update mod.methods_hash
+ klass.constants_hash.update mod.constants_hash
+
+ klass.current_section = mod.current_section
+ klass.in_files.concat mod.in_files
+ klass.sections.concat mod.sections
+ klass.unmatched_alias_lists = mod.unmatched_alias_lists
+ klass.current_section = mod.current_section
+ klass.visibility = mod.visibility
+
+ klass.classes_hash.update mod.classes_hash
+ klass.modules_hash.update mod.modules_hash
+ klass.metadata.update mod.metadata
+
+ klass.document_self = mod.received_nodoc ? nil : mod.document_self
+ klass.document_children = mod.document_children
+ klass.force_documentation = mod.force_documentation
+ klass.done_documenting = mod.done_documenting
+
+ # update the parent of all children
+
+ (klass.attributes
+ klass.method_list +
+ klass.aliases +
+ klass.external_aliases +
+ klass.constants +
+ klass.includes +
+ klass.classes +
+ klass.modules).each do |obj|
+ obj.parent = klass
+ end
+
+ klass
+ end
+
+ ##
+ # Creates a new ClassModule with +name+ with optional +superclass+
+ #
+ # This is a constructor for subclasses, and must never be called directly.
+
+ def initialize(name, superclass = nil)
+ @constant_aliases = []
+ @diagram = nil
+ @full_name = nil
+ @is_alias_for = nil
+ @name = name
+ @superclass = superclass
super()
end
##
- # Ancestors list for this ClassModule (abstract)
+ # Ancestors list for this ClassModule: the list of included modules
+ # (classes will add their superclass if any).
+ #
+ # Returns the included classes or modules, not the includes
+ # themselves. If the include is just a String, though, it is returned as is.
def ancestors
- raise NotImplementedError
+ includes.map { |i| i.is_a?(String) ? i : i.module }
end
##
# Appends +comment+ to the current comment, but separated by a rule. Works
# more like <tt>+=</tt>.
- def comment=(comment)
+ def comment= comment
return if comment.empty?
comment = "#{@comment}\n---\n#{normalize_comment comment}" unless
@@ -42,9 +113,22 @@ def comment=(comment)
end
##
+ # Looks for a symbol in the #ancestors. See Context#find_local_symbol.
+
+ def find_ancestor_local_symbol symbol
+ ancestors.each do |m|
+ next if m.is_a?(String)
+ res = m.find_local_symbol(symbol)
+ return res if res
+ end
+
+ nil
+ end
+
+ ##
# Finds a class or module with +name+ in this namespace or its descendents
- def find_class_named(name)
+ def find_class_named name
return self if full_name == name
return self if @name == name
@@ -66,13 +150,16 @@ def full_name
end
##
- # 'module' or 'class'
+ # Sets the full_name overriding any computed full name.
+ #
+ # Used for modules and classes that are constant aliases.
- def type
- module? ? 'module' : 'class'
+ def full_name= full_name
+ @full_name = full_name
end
def marshal_dump # :nodoc:
+ # TODO must store the singleton attribute
attrs = attributes.sort.map do |attr|
[attr.name, attr.rw]
end
@@ -106,10 +193,13 @@ def marshal_dump # :nodoc:
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
@name = array[1]
@full_name = array[2]
@@ -184,31 +274,59 @@ def module?
end
##
+ # Allows overriding the initial name.
+ #
+ # Used for modules and classes that are constant aliases.
+
+ def name= new_name
+ @name = new_name
+ end
+
+ ##
# Path to this class or module
def path
http_url RDoc::RDoc.current.generator.class_dir
end
##
+ # Name to use to generate the url:
+ # modules and classes that are aliases for another
+ # module or classe return the name of the latter.
+
+ def name_for_path
+ is_alias_for ? is_alias_for.full_name : full_name
+ end
+
+ ##
# Get the superclass of this class. Attempts to retrieve the superclass
# object, returns the name if it is not known.
def superclass
- RDoc::TopLevel.find_class_named_from(@superclass, parent) || @superclass
+ RDoc::TopLevel.find_class_named(@superclass) || @superclass
end
##
# Set the superclass of this class to +superclass+
def superclass=(superclass)
raise NoMethodError, "#{full_name} is a module" if module?
-
- @superclass = superclass if @superclass.nil? or @superclass == 'Object'
+ @superclass = superclass
end
def to_s # :nodoc:
- "#{self.class}: #{full_name} #{@comment} #{super}"
+ if is_alias_for then
+ "#{self.class.name} #{self.full_name} -> #{is_alias_for}"
+ else
+ super
+ end
+ end
+
+ ##
+ # 'module' or 'class'
+
+ def type
+ module? ? 'module' : 'class'
end
end
View
81 lib/rdoc/code_object.rb
@@ -12,15 +12,16 @@
# * RDoc::Context
# * RDoc::TopLevel
# * RDoc::ClassModule
-# * RDoc::AnonClass
+# * RDoc::AnonClass (never used so far)
# * RDoc::NormalClass
# * RDoc::NormalModule
# * RDoc::SingleClass
-# * RDoc::AnyMethod
-# * RDoc::GhostMethod
-# * RDoc::MetaMethod
+# * RDoc::MethodAttr
+# * RDoc::Attr
+# * RDoc::AnyMethod
+# * RDoc::GhostMethod
+# * RDoc::MetaMethod
# * RDoc::Alias
-# * RDoc::Attr
# * RDoc::Constant
# * RDoc::Require
# * RDoc::Include
@@ -47,12 +48,12 @@ class RDoc::CodeObject
##
# Are we done documenting (ie, did we come across a :enddoc:)?
- attr_accessor :done_documenting
+ attr_reader :done_documenting
##
# Force documentation of this CodeObject
- attr_accessor :force_documentation
+ attr_reader :force_documentation
##
# Hash of arbitrary metadata for this CodeObject
@@ -65,6 +66,11 @@ class RDoc::CodeObject
attr_accessor :parent
##
+ # Did we ever receive a +:nodoc:+ directive?
+
+ attr_reader :received_nodoc
+
+ ##
# Which section are we in
attr_accessor :section
@@ -87,6 +93,7 @@ def initialize
@document_self = true
@done_documenting = false
@force_documentation = false
+ @received_nodoc = false
@parent = nil
end
@@ -108,62 +115,78 @@ def comment=(comment)
end
##
- # Enables or disables documentation of this CodeObject's children. Calls
- # remove_classes_and_modules when disabling.
+ # Enables or disables documentation of this CodeObject's children unless it
+ # has been turned off by :enddoc:
def document_children=(document_children)
- @document_children = document_children
- remove_classes_and_modules unless document_children
+ @document_children = document_children unless @done_documenting
end
##
- # Enables or disables documentation of this CodeObject. Calls
- # remove_methods_etc when disabling.
+ # Enables or disables documentation of this CodeObject unless it has been
+ # turned off by :enddoc:. If the argument is +nil+ it means the
+ # documentation is turned off by +:nodoc:+.
def document_self=(document_self)
+ return if @done_documenting
+
@document_self = document_self
- remove_methods_etc unless document_self
+ @received_nodoc = true if document_self.nil?
end
##
- # Does this class have a comment with content or is document_self false.
+ # Does this object have a comment with content or is #received_nodoc true?
def documented?
- !(@document_self and @comment.empty?)
+ @received_nodoc or !@comment.empty?
end
##
- # File name of our parent
+ # Turns documentation on/off, and turns on/off #document_self
+ # and #document_children.
+ #
+ # Once documentation has been turned off (by +:enddoc:+),
+ # the object will refuse to turn #document_self or
+ # #document_children on, so +:doc:+ and +:start_doc:+ directives
+ # will have no effect in the current file.
- def parent_file_name
- @parent ? @parent.base_name : '(unknown)'
+ def done_documenting=(value)
+ @done_documenting = value
+ @document_self = !value
+ @document_children = @document_self
end
##
- # Name of our parent
+ # Force the documentation of this object unless documentation
+ # has been turned off by :endoc:
+ #--
+ # HACK untested, was assigning to an ivar
- def parent_name
- @parent ? @parent.full_name : '(unknown)'
+ def force_documentation=(value)
+ @force_documentation = value unless @done_documenting
end
##
- # Callback called upon disabling documentation of children. See
- # #document_children=
+ # File name of our parent
- def remove_classes_and_modules
+ def parent_file_name
+ @parent ? @parent.base_name : '(unknown)'
end
##
- # Callback called upon disabling documentation of ourself. See
- # #document_self=
+ # Name of our parent
- def remove_methods_etc
+ def parent_name
+ @parent ? @parent.full_name : '(unknown)'
end
##
- # Enable capture of documentation
+ # Enable capture of documentation unless documentation has been
+ # turned off by :endoc:
def start_doc
+ return if @done_documenting
+
@document_self = true
@document_children = true
end
View
33 lib/rdoc/constant.rb
@@ -6,6 +6,13 @@
class RDoc::Constant < RDoc::CodeObject
##
+ # If this constant is an alias for a module or class,
+ # this is the RDoc::ClassModule it is an alias for.
+ # +nil+ otherwise.
+
+ attr_accessor :is_alias_for
+
+ ##
# The constant's name
attr_accessor :name
@@ -22,6 +29,7 @@ def initialize(name, value, comment)
super()
@name = name
@value = value
+ @is_alias_for = nil
self.comment = comment
end
@@ -40,11 +48,19 @@ def == other
@name == other.name
end
+ ##
+ # A constant is documented if it has a comment, or is an alias
+ # for a documented class or module.
+
+ def documented?
+ super or is_alias_for && is_alias_for.documented?
+ end
+
def inspect # :nodoc:
- "#<%s:0x%x %s::%s>" % [
- self.class, object_id,
- parent_name, @name,
- ]
+ "#<%s:0x%x %s::%s>" % [
+ self.class, object_id,
+ parent_name, @name,
+ ]
end
##
@@ -54,5 +70,14 @@ def path
"#{@parent.path}##{@name}"
end
+ def to_s # :nodoc:
+ parent_name = parent ? parent.full_name : '(unknown)'
+ if is_alias_for
+ "constant #{parent_name}::#@name -> #{is_alias_for}"
+ else
+ "constant #{parent_name}::#@name"
+ end
+ end
+
end
View
685 lib/rdoc/context.rb
@@ -15,17 +15,12 @@ class RDoc::Context < RDoc::CodeObject
TYPES = %w[class instance]
##
- # Method visibilities
-
- VISIBILITIES = [:public, :protected, :private]
-
- ##
- # Aliased methods
+ # Class/module aliases
attr_reader :aliases
##
- # attr* methods
+ # All attr* methods
attr_reader :attributes
@@ -37,7 +32,7 @@ class RDoc::Context < RDoc::CodeObject
##
# Current section of documentation
- attr_reader :current_section
+ attr_accessor :current_section
##
# Files this context is found in
@@ -70,19 +65,37 @@ class RDoc::Context < RDoc::CodeObject
attr_reader :sections
##
- # Aliases that haven't been resolved to a method
+ # Hash <tt>old_name => [aliases]</tt>, for aliases
+ # that haven't (yet) been resolved to a method/attribute.
+ # (Not to be confused with the aliases of the context.)
attr_accessor :unmatched_alias_lists
##
+ # Aliases that could not eventually be resolved.
+
+ attr_reader :external_aliases
+
+ ##
# Current visibility of this context
- attr_reader :visibility
+ attr_accessor :visibility
+
+ ##
+ # Hash of registered methods. Attributes are also registered here,
+ # twice if they are RW.
+
+ attr_reader :methods_hash
+
+ ##
+ # Hash of registered constants.
+
+ attr_reader :constants_hash
##
# A per-comment section of documentation like:
#
- # # :SECTION: The title
+ # # :section: The title
# # The body
class Section
@@ -137,14 +150,12 @@ def inspect # :nodoc:
end
##
- # Set the comment for this section from the original comment block If
+ # Set the comment for this section from the original comment block. If
# the first line contains :section:, strip it and use the rest.
# Otherwise remove lines up to the line containing :section:, and look
# for those lines again at the end and remove them. This lets us write
#
- # # blah blah blah
- # #
- # # :SECTION: The title
+ # # :section: The title
# # The body
def set_comment(comment)
@@ -169,7 +180,7 @@ def set_comment(comment)
end
##
- # Creates an unnamed empty context with public visibility
+ # Creates an unnamed empty context with public current visibility
def initialize
super
@@ -184,16 +195,10 @@ def initialize
@current_section = Section.new self, nil, nil
@sections = [@current_section]
- initialize_methods_etc
- initialize_classes_and_modules
- end
-
- ##
- # Sets the defaults for classes and modules
-
- def initialize_classes_and_modules
@classes = {}
@modules = {}
+
+ initialize_methods_etc
end
##
@@ -206,10 +211,14 @@ def initialize_methods_etc
@requires = []
@includes = []
@constants = []
+ @external_aliases = []
# This Hash maps a method name to a list of unmatched aliases (aliases of
# a method not yet encountered).
@unmatched_alias_lists = {}
+
+ @methods_hash = {}
+ @constants_hash = {}
end
##
@@ -220,142 +229,209 @@ def <=>(other)
end
##
- # Adds +an_alias+ that is automatically resolved to it's corresponding
- # RDoc::AnyMethod object.
+ # Adds +an_alias+ that is automatically resolved
def add_alias an_alias
- old_name = an_alias.old_name
+ return an_alias unless @document_self
- meth = if an_alias.singleton then
- find_class_method_named old_name
- else
- find_instance_method_named old_name
- end
+ method_attr = find_method(an_alias.old_name, an_alias.singleton) ||
+ find_attribute(an_alias.old_name, an_alias.singleton)
- if meth then
- add_alias_impl an_alias, meth
+ if method_attr then
+ method_attr.add_alias an_alias, self
else
- add_to @aliases, an_alias
- unmatched_alias_list = @unmatched_alias_lists[old_name] ||= []
+ add_to @external_aliases, an_alias
+ unmatched_alias_list = @unmatched_alias_lists[an_alias.pretty_old_name] ||= []
unmatched_alias_list.push an_alias
end
an_alias
end
##
- # Turns +an_alias+ into an AnyMethod that points to +meth+
-
- def add_alias_impl(an_alias, meth)
- new_meth = RDoc::AnyMethod.new an_alias.text, an_alias.new_name
- new_meth.is_alias_for = meth
- new_meth.singleton = meth.singleton
- new_meth.params = meth.params
-
- new_meth.comment = an_alias.comment
-
- meth.add_alias new_meth
-
- add_method new_meth
-
- # aliases don't use ongoing visibility
- new_meth.visibility = meth.visibility
-
- new_meth
- end
-
- ##
- # Adds +attribute+
-
- def add_attribute(attribute)
- add_to @attributes, attribute
+ # Adds +attribute+ if not already there. If it is (as method(s) or attribute),
+ # updates the comment if it was empty.
+ #
+ # The attribute is registered only if it defines a new method.
+ # For instance, <tt>attr_reader :foo</tt> will not be registered
+ # if method +foo+ exists, but <tt>attr_accessor :foo</tt> will be registered
+ # if method +foo+ exists, but <tt>foo=</tt> does not.
+
+ def add_attribute attribute
+ return attribute unless @document_self
+
+ # mainly to check for redefinition of an attribute as a method
+ # TODO find a policy for 'attr_reader :foo' + 'def foo=()'
+ register = false
+ if attribute.rw.index('R')
+ key = attribute.pretty_name
+ known = @methods_hash[key]
+ if known
+ #$stderr.puts "\n#{display(attribute)} already registered as #{display(known)}"
+ known.comment = attribute.comment if known.comment.empty?
+ else
+ @methods_hash[key] = attribute
+ register = true
+ end
+ end
+ if attribute.rw.index('W')
+ key = attribute.pretty_name << '='
+ known = @methods_hash[key]
+ if known
+ #$stderr.puts "\n#{display(attribute)} already registered as #{display(known)}"
+ known.comment = attribute.comment if known.comment.empty?
+ else
+ @methods_hash[key] = attribute
+ register = true
+ end
+ end
+ if register
+ attribute.visibility = @visibility
+ add_to @attributes, attribute
+ resolve_aliases attribute
+ end
end
##
- # Adds a class named +name+ with +superclass+.
+ # Adds a class named +given_name+ with +superclass+.
+ #
+ # Both +given_name+ and +superclass+ may contain '::', and are
+ # interpreted relative to the +self+ context. This allows handling correctly
+ # examples like these:
+ # class RDoc::Gauntlet < Gauntlet
+ # module Mod
+ # class Object # implies < ::Object
+ # class SubObject < Object # this is _not_ ::Object
#
# Given <tt>class Container::Item</tt> RDoc assumes +Container+ is a module
- # unless it later sees <tt>class Container</tt>. add_class automatically
- # upgrades +name+ to a class in this case.
-
- def add_class(class_type, name, superclass = 'Object')
- klass = add_class_or_module @classes, class_type, name, superclass
-
- existing = klass.superclass
- existing = existing.name if existing and not String === existing
-
- if superclass != existing and superclass != 'Object' then
- klass.superclass = superclass
+ # unless it later sees <tt>class Container</tt>. +add_class+ automatically
+ # upgrades +given_name+ to a class in this case.
+
+ def add_class class_type, given_name, superclass = '::Object'
+
+ # superclass +nil+ is passed by the C parser in the following cases:
+ # - registering Object in 1.8 (correct)
+ # - registering BasicObject in 1.9 (correct)
+ # - registering RubyVM in 1.9 in iseq.c (incorrect: < Object in vm.c)
+ # => if we later find a superclass for a registered class with a nil superclass,
+ # we must honor it.
+
+ # find the name & enclosing context
+ if given_name =~ /^:+(\w+)$/
+ full_name = $1
+ enclosing = top_level
+ name = full_name.split(/:+/).last
+ else
+ full_name = child_name(given_name)
+ if full_name =~ /^(.+)::(\w+)$/
+ name = $2
+ enclosing = RDoc::TopLevel.classes_hash[$1] || RDoc::TopLevel.modules_hash[$1]
+ else
+ name = full_name
+ enclosing = self
+ end
end
- # If the parser encounters Container::Item before encountering
- # Container, then it assumes that Container is a module. This may not
- # be the case, so remove Container from the module list if present and
- # transfer any contained classes and modules to the new class.
-
- mod = RDoc::TopLevel.modules_hash.delete klass.full_name
-
- if mod then
- klass.classes_hash.update mod.classes_hash
- klass.modules_hash.update mod.modules_hash
- klass.method_list.concat mod.method_list
-
- @modules.delete klass.name
+ # find the superclass full name
+ if superclass
+ if superclass =~ /^:+/
+ superclass = $' #'
+ else
+ if superclass =~ /^(\w+):+(.+)$/
+ suffix = $2
+ mod = find_module_named($1)
+ superclass = mod.full_name + '::' + suffix if mod
+ else
+ mod = find_module_named(superclass)
+ superclass = mod.full_name if mod
+ end
+ end
+ # did we believed it was a module?
+ mod = RDoc::TopLevel.modules_hash.delete(superclass)
+ if mod
+ super_context = mod.parent
+ super_context.modules_hash.delete mod.name
+ sklass = RDoc::ClassModule.from_module(RDoc::NormalClass, mod) # TODO check: could it be RDoc::AnyClass?
+ # if it was there, then we keep it even if mod.parent.done_documenting
+ RDoc::TopLevel.classes_hash[sklass.full_name] = sklass
+ super_context.classes_hash[sklass.name] = sklass
+ end
+ if superclass == full_name
+ # e.g., Object < Object
+ superclass = nil
+ end
end
- RDoc::TopLevel.classes_hash[klass.full_name] = klass
+ klass = RDoc::TopLevel.classes_hash[full_name]
+ if klass
+ # if TopLevel, it may not be registered in the classes:
+ enclosing.classes_hash[name] = klass
+ # update the superclass if needed
+ if superclass
+ existing = klass.superclass
+ existing = existing.full_name unless existing.is_a?(String) if existing
+ if existing.nil? || (existing == 'Object' && superclass != 'Object')
+ klass.superclass = superclass
+ end
+ end
+ else
+ # this is a new class
+ mod = RDoc::TopLevel.modules_hash.delete(full_name)
+ if mod
+ # it was registered as a module, so transform it to a class
+ enclosing.modules_hash.delete name
+ klass = RDoc::ClassModule.from_module(class_type, mod)
+ klass.superclass = superclass unless superclass.nil?
+ # if it was there, then we keep it even if done_documenting
+ RDoc::TopLevel.classes_hash[full_name] = klass
+ enclosing.classes_hash[name] = klass
+ else
+ klass = class_type.new(name, superclass)
+ enclosing.add_class_or_module(klass, enclosing.classes_hash, RDoc::TopLevel.classes_hash)
+ end
+ end
klass
end
##
- # Instantiates a +class_type+ named +name+ and adds it the modules or
- # classes Hash +collection+.
+ # Adds the class or module +mod+ to the modules or
+ # classes Hash +self_hash+, and to +all_hash+ (either
+ # <tt>TopLevel::modules_hash</tt> or <tt>TopLevel::classes_hash</tt>),
+ # unless #done_documenting is +true+. Sets the #parent of +mod+
+ # to +self+, and its #section to #current_section. Returns +mod+.
- def add_class_or_module(collection, class_type, name, superclass = nil)
- full_name = child_name name
-
- mod = collection[name]
-
- if mod then
- mod.superclass = superclass unless mod.module?
- else
- all = if class_type == RDoc::NormalModule then
- RDoc::TopLevel.modules_hash
- else
- RDoc::TopLevel.classes_hash
- end
-
- mod = all[full_name]
-
- unless mod then
- mod = class_type.new name, superclass
- else
- # If the class has been encountered already, check that its
- # superclass has been set (it may not have been, depending on the
- # context in which it was encountered).
- if class_type == RDoc::NormalClass then
- mod.superclass = superclass unless mod.superclass
- end
- end
-
- unless @done_documenting then
- all[full_name] = mod
- collection[name] = mod
- end
-
- mod.section = @current_section
- mod.parent = self
+ def add_class_or_module mod, self_hash, all_hash
+ mod.section = @current_section # TODO declaring context? something is wrong here...
+ mod.parent = self
+ unless @done_documenting then
+ self_hash[mod.name] = mod
+ # this must be done AFTER adding mod to its parent,
+ # so that the full name is correct:
+ all_hash[mod.full_name] = mod
end
-
mod
end
##
- # Adds +constant+
+ # Adds +constant+ if not already there. If it is, updates the comment,
+ # value and/or is_alias_for of the known constant if they were empty/nil.
def add_constant(constant)
- add_to @constants, constant
+ return constant unless @document_self
+
+ # HACK: avoid duplicate 'PI' & 'E' in math.c (1.8.7 source code)
+ # (this is a #ifdef: should be handled by the C parser)
+ known = @constants_hash[constant.name]
+ if known
+ #$stderr.puts "\nconstant #{constant.name} already registered"
+ known.comment = constant.comment if known.comment.empty?
+ known.value = constant.value if known.value.nil? or known.value.strip.empty?
+ known.is_alias_for ||= constant.is_alias_for
+ else
+ @constants_hash[constant.name] = constant
+ add_to @constants, constant
+ end
end
##
@@ -366,60 +442,77 @@ def add_include(include)
end
##
- # Adds +method+
+ # Adds +method+ if not already there. If it is (as method or attribute),
+ # updates the comment if it was empty.
def add_method(method)
- method.visibility = @visibility
- add_to @method_list, method
-
- unmatched_alias_list = @unmatched_alias_lists[method.name]
- if unmatched_alias_list then
- unmatched_alias_list.each do |unmatched_alias|
- add_alias_impl unmatched_alias, method
- @aliases.delete unmatched_alias
- end
-
- @unmatched_alias_lists.delete method.name
+ return method unless @document_self
+
+ # HACK: avoid duplicate 'new' in io.c & struct.c (1.8.7 source code)
+ key = method.pretty_name
+ known = @methods_hash[key]
+ if known
+ # TODO issue stderr messages if --verbose
+ #$stderr.puts "\n#{display(method)} already registered as #{display(known)}"
+ known.comment = method.comment if known.comment.empty?
+ else
+ @methods_hash[key] = method
+ method.visibility = @visibility
+ add_to @method_list, method
+ resolve_aliases method
end
end
##
# Adds a module named +name+. If RDoc already knows +name+ is a class then
- # that class is returned instead. See also #add_class
+ # that class is returned instead. See also #add_class.
def add_module(class_type, name)
- return @classes[name] if @classes.key? name
-
- add_class_or_module @modules, class_type, name, nil
+ mod = @classes[name] || @modules[name]
+ return mod if mod
+ full_name = child_name(name)
+ mod = RDoc::TopLevel.modules_hash[full_name] || class_type.new(name)
+ add_class_or_module(mod, @modules, RDoc::TopLevel.modules_hash)
end
##
- # Adds an alias from +from+ to +name+
+ # Adds an alias from +from+ (a class or module) to +name+.
def add_module_alias from, name
- to_name = child_name name
+ return from if @done_documenting
- unless @done_documenting then
- if from.module? then
- RDoc::TopLevel.modules_hash
- else
- RDoc::TopLevel.classes_hash
- end[to_name] = from
+ to_name = child_name(name)
- if from.module? then
- @modules
- else
- @classes
- end[name] = from
+ # if we already know this name, don't register an alias:
+ # see the metaprogramming in lib/active_support/basic_object.rb,
+ # where we already know BasicObject as a class when we find
+ # BasicObject = BlankSlate
+ return from if RDoc::TopLevel.find_class_or_module(to_name)
+
+ if from.module? then
+ RDoc::TopLevel.modules_hash[to_name] = from
+ @modules[name] = from
+ else
+ RDoc::TopLevel.classes_hash[to_name] = from
+ @classes[name] = from
end
+ # HACK: register a constant for this alias:
+ # constant value and comment will be updated after,
+ # when the Ruby parser adds the constant
+ const = RDoc::Constant.new(name, nil, '')
+ const.is_alias_for = from
+ add_constant const
+
from
end
##
# Adds +require+ to this context's top level
def add_require(require)
+ return require unless @document_self
+
if RDoc::TopLevel === self then
add_to @requires, require
else
@@ -431,23 +524,58 @@ def add_require(require)
# Adds +thing+ to the collection +array+
def add_to(array, thing)
- array << thing if @document_self and not @done_documenting
+ array << thing if @document_self
thing.parent = self
thing.section = @current_section
end
##
+ # Is there any content?
+ # This means any of: comment, aliases, methods, attributes,
+ # external aliases, require, constant.
+ # Includes are also checked unless <tt>includes == false</tt>.
+
+ def any_content(includes = true)
+ @any_content ||= !(
+ @comment.empty? &&
+ @method_list.empty? &&
+ @attributes.empty? &&
+ @aliases.empty? &&
+ @external_aliases.empty? &&
+ @requires.empty? &&
+ @constants.empty?
+ )
+ @any_content || (includes && !@includes.empty?)
+ end
+
+ ##
# Creates the full name for a child with +name+
def child_name name
- if RDoc::TopLevel === self then
+ if name =~ /^:+/
+ $' #'
+ elsif RDoc::TopLevel === self then
name
else
"#{self.full_name}::#{name}"
end
end
##
+ # Class attributes
+
+ def class_attributes
+ @class_attributes ||= attributes.select { |a| a.singleton }
+ end
+
+ ##
+ # Class methods
+
+ def class_method_list
+ @class_method_list ||= method_list.select { |a| a.singleton }
+ end
+
+ ##
# Array of classes in this context
def classes
@@ -475,6 +603,14 @@ def defined_in?(file)
@in_files.include?(file)
end
+ def display(method_attr) # :nodoc:
+ if method_attr.is_a? RDoc::Attr
+ "#{method_attr.definition} #{method_attr.pretty_name}"
+ else
+ "method #{method_attr.pretty_name}"
+ end
+ end
+
##
# Iterator for attributes
@@ -511,10 +647,25 @@ def each_method # :yields: method
end
##
+ # Finds an attribute +name+ with singleton value +singleton+.
+
+ def find_attribute(name, singleton)
+ name = $1 if name =~ /^(.*)=$/
+ @attributes.find { |a| a.name == name && a.singleton == singleton }
+ end
+
+ ##
# Finds an attribute with +name+ in this context
def find_attribute_named(name)
- @attributes.find { |m| m.name == name }
+ case name
+ when /\A#/ then
+ find_attribute name[1..-1], false
+ when /\A::/ then
+ find_attribute name[2..-1], true
+ else
+ @attributes.find { |a| a.name == name }
+ end
end
##
@@ -539,6 +690,27 @@ def find_enclosing_module_named(name)
end
##
+ # Finds an external alias +name+ with singleton value +singleton+.
+
+ def find_external_alias(name, singleton)
+ @external_aliases.find { |m| m.name == name && m.singleton == singleton }
+ end
+
+ ##
+ # Finds an external alias with +name+ in this context
+
+ def find_external_alias_named(name)
+ case name
+ when /\A#/ then
+ find_external_alias name[1..-1], false
+ when /\A::/ then
+ find_external_alias name[2..-1], true
+ else
+ @external_aliases.