summaryrefslogtreecommitdiff
path: root/lib/rdoc/parser
diff options
context:
space:
mode:
authordrbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2010-12-20 03:22:49 +0000
committerdrbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2010-12-20 03:22:49 +0000
commit2ef9c50c6e405717d06362787c4549ca4f1c6485 (patch)
treeee99486567461dd5796f3d6edcc9e204187f2666 /lib/rdoc/parser
parentd7effd506f5b91a636f2e6452ef1946b923007c7 (diff)
Import RDoc 3
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@30249 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/rdoc/parser')
-rw-r--r--lib/rdoc/parser/c.rb414
-rw-r--r--lib/rdoc/parser/perl.rb165
-rw-r--r--lib/rdoc/parser/ruby.rb333
-rw-r--r--lib/rdoc/parser/ruby_tools.rb5
-rw-r--r--lib/rdoc/parser/simple.rb13
5 files changed, 536 insertions, 394 deletions
diff --git a/lib/rdoc/parser/c.rb b/lib/rdoc/parser/c.rb
index e218298dfe..60e9fefd61 100644
--- a/lib/rdoc/parser/c.rb
+++ b/lib/rdoc/parser/c.rb
@@ -3,9 +3,9 @@ require 'rdoc/parser/ruby'
require 'rdoc/known_classes'
##
-# We attempt to parse C extension files. Basically we look for
+# RDoc::Parser::C attempts to parse C extension files. It looks for
# the standard patterns that you find in extensions: <tt>rb_define_class,
-# rb_define_method</tt> and so on. We also try to find the corresponding
+# rb_define_method</tt> and so on. It tries to find the corresponding
# C source for the methods and extract comments, but if we fail
# we don't worry too much.
#
@@ -49,13 +49,26 @@ require 'rdoc/known_classes'
#
# The comment blocks may include special directives:
#
-# [Document-class: <i>name</i>]
-# This comment block is documentation for the given class. Use this
-# when the <tt>Init_xxx</tt> method is not named after the class.
+# [Document-class: +name+]
+# Documentation for the named class.
#
-# [Document-method: <i>name</i>]
-# This comment documents the named method. Use when RDoc cannot
-# automatically find the method from it's declaration
+# [Document-module: +name+]
+# Documentation for the named module.
+#
+# [Document-const: +name+]
+# Documentation for the named +rb_define_const+.
+#
+# [Document-global: +name+]
+# Documentation for the named +rb_define_global_const+
+#
+# [Document-variable: +name+]
+# Documentation for the named +rb_define_variable+
+#
+# [Document-method: +name+]
+# Documentation for the named method.
+#
+# [Document-attr: +name+]
+# Documentation for the named attribute.
#
# [call-seq: <i>text up to an empty line</i>]
# Because C source doesn't give descripive names to Ruby-level parameters,
@@ -120,21 +133,61 @@ 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
@file_dir = File.dirname(@file_name)
end
+ ##
+ # Scans #content for rb_define_alias
+
def do_aliases
- @content.scan(%r{rb_define_alias\s*\(\s*(\w+),\s*"([^"]+)",\s*"([^"]+)"\s*\)}m) do
- |var_name, new_name, old_name|
+ @content.scan(/rb_define_alias\s*\(
+ \s*(\w+),
+ \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_obj = find_class var_name, class_name
+
+ al = RDoc::Alias.new '', old_name, new_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
+
+ class_obj.add_alias al
+ @stats.add_alias al
+ end
+ end
- as = class_obj.add_alias RDoc::Alias.new("", old_name, new_name, "")
+ ##
+ # Scans #content for rb_attr and rb_define_attr
+
+ def do_attrs
+ @content.scan(/rb_attr\s*\(
+ \s*(\w+),
+ \s*([\w"()]+),
+ \s*([01]),
+ \s*([01]),
+ \s*\w+\);/xm) do |var_name, attr_name, read, write|
+ handle_attr var_name, attr_name, read, write
+ end
- @stats.add_alias as
+ @content.scan(%r%rb_define_attr\(
+ \s*([\w\.]+),
+ \s*"([^"]+)",
+ \s*(\d+),
+ \s*(\d+)\s*\);
+ %xm) do |var_name, attr_name, read, write|
+ handle_attr var_name, attr_name, read, write
end
end
+ ##
+ # Scans #content for rb_define_module, rb_define_class, boot_defclass,
+ # rb_define_module_under, rb_define_class_under and rb_singleton_class
+
def do_classes
@content.scan(/(\w+)\s* = \s*rb_define_module\s*\(\s*"(\w+)"\s*\)/mx) do
|var_name, class_name|
@@ -165,35 +218,44 @@ class RDoc::Parser::C < RDoc::Parser
end
@content.scan(/([\w\.]+)\s* = \s*rb_define_class_under\s*
- \(
- \s*(\w+),
- \s*"(\w+)",
- \s*([\w\*\s\(\)\.\->]+)\s* # for SWIG
- \s*\)/mx) do |var_name, in_module, class_name, parent|
+ \(
+ \s*(\w+),
+ \s*"(\w+)",
+ \s*([\w\*\s\(\)\.\->]+)\s* # for SWIG
+ \s*\)/mx) do |var_name, in_module, class_name, parent|
handle_class_module(var_name, "class", class_name, parent, in_module)
end
+
+ @content.scan(/([\w\.]+)\s* = \s*rb_singleton_class\s*
+ \(
+ \s*(\w+)
+ \s*\)/mx) do |sclass_var, class_var|
+ handle_singleton sclass_var, class_var
+ end
end
+ ##
+ # Scans #content for rb_define_variable, rb_define_readonly_variable,
+ # rb_define_const and rb_define_global_const
+
def do_constants
- @content.scan(%r{\Wrb_define_
+ @content.scan(%r%\Wrb_define_
( variable |
readonly_variable |
const |
- global_const | )
+ global_const )
\s*\(
(?:\s*(\w+),)?
\s*"(\w+)",
\s*(.*?)\s*\)\s*;
- }xm) do |type, var_name, const_name, definition|
+ %xm) do |type, var_name, const_name, definition|
var_name = "rb_cObject" if !var_name or var_name == "rb_mKernel"
handle_constants type, var_name, const_name, definition
end
end
##
- # Look for includes of the form:
- #
- # rb_include_module(rb_cArray, rb_mEnumerable);
+ # Scans #content for rb_include_module
def do_includes
@content.scan(/rb_include_module\s*\(\s*(\w+?),\s*(\w+?)\s*\)/) do |c,m|
@@ -204,8 +266,13 @@ class RDoc::Parser::C < RDoc::Parser
end
end
+ ##
+ # Scans #content for rb_define_method, rb_define_singleton_method,
+ # rb_define_module_function, rb_define_private_method,
+ # rb_define_global_function and define_filetest_function
+
def do_methods
- @content.scan(%r{rb_define_
+ @content.scan(%r%rb_define_
(
singleton_method |
method |
@@ -217,8 +284,7 @@ class RDoc::Parser::C < RDoc::Parser
\s*(?:RUBY_METHOD_FUNC\(|VALUEFUNC\()?(\w+)\)?,
\s*(-?\w+)\s*\)
(?:;\s*/[*/]\s+in\s+(\w+?\.[cy]))?
- }xm) do
- |type, var_name, meth_name, meth_body, param_count, source_file|
+ %xm) do |type, var_name, meth_name, meth_body, param_count, source_file|
# Ignore top-object and weird struct.c dynamic stuff
next if var_name == "ruby_top_self"
@@ -231,44 +297,69 @@ class RDoc::Parser::C < RDoc::Parser
source_file)
end
- @content.scan(%r{rb_define_attr\(
- \s*([\w\.]+),
- \s*"([^"]+)",
- \s*(\d+),
- \s*(\d+)\s*\);
- }xm) do |var_name, attr_name, attr_reader, attr_writer|
- #var_name = "rb_cObject" if var_name == "rb_mKernel"
- handle_attr(var_name, attr_name,
- attr_reader.to_i != 0,
- attr_writer.to_i != 0)
- end
-
- @content.scan(%r{rb_define_global_function\s*\(
+ @content.scan(%r%rb_define_global_function\s*\(
\s*"([^"]+)",
\s*(?:RUBY_METHOD_FUNC\(|VALUEFUNC\()?(\w+)\)?,
\s*(-?\w+)\s*\)
(?:;\s*/[*/]\s+in\s+(\w+?\.[cy]))?
- }xm) do |meth_name, meth_body, param_count, source_file|
+ %xm) do |meth_name, meth_body, param_count, source_file|
handle_method("method", "rb_mKernel", meth_name,
meth_body, param_count, source_file)
end
@content.scan(/define_filetest_function\s*\(
- \s*"([^"]+)",
- \s*(?:RUBY_METHOD_FUNC\(|VALUEFUNC\()?(\w+)\)?,
- \s*(-?\w+)\s*\)/xm) do
- |meth_name, meth_body, param_count|
+ \s*"([^"]+)",
+ \s*(?:RUBY_METHOD_FUNC\(|VALUEFUNC\()?(\w+)\)?,
+ \s*(-?\w+)\s*\)/xm) do |meth_name, meth_body, param_count|
handle_method("method", "rb_mFileTest", meth_name, meth_body, param_count)
handle_method("singleton_method", "rb_cFile", meth_name, meth_body, param_count)
end
end
- def find_attr_comment(attr_name)
- if @content =~ %r{((?>/\*.*?\*/\s+))
- rb_define_attr\((?:\s*(\w+),)?\s*"#{attr_name}"\s*,.*?\)\s*;}xmi
+ ##
+ # Finds the comment for an alias on +class_name+ from +new_name+ to
+ # +old_name+
+
+ def find_alias_comment class_name, new_name, old_name
+ content =~ %r%((?>/\*.*?\*/\s+))
+ rb_define_alias\(\s*#{Regexp.escape class_name}\s*,
+ \s*"#{Regexp.escape new_name}"\s*,
+ \s*"#{Regexp.escape old_name}"\s*\);%xm
+
+ $1 || ''
+ end
+
+ ##
+ # Finds a comment for rb_define_attr, rb_attr or Document-attr.
+ #
+ # +var_name+ is the C class variable the attribute is defined on.
+ # +attr_name+ is the attribute's name.
+ #
+ # +read+ and +write+ are the read/write flags ('1' or '0'). Either both or
+ # neither must be provided.
+
+ def find_attr_comment var_name, attr_name, read = nil, write = nil
+ attr_name = Regexp.escape attr_name
+
+ rw = if read and write then
+ /\s*#{read}\s*,\s*#{write}\s*/xm
+ else
+ /.*?/m
+ end
+
+ if @content =~ %r%((?>/\*.*?\*/\s+))
+ rb_define_attr\((?:\s*#{var_name},)?\s*
+ "#{attr_name}"\s*,
+ #{rw}\)\s*;%xm then
+ $1
+ elsif @content =~ %r%((?>/\*.*?\*/\s+))
+ rb_attr\(\s*#{var_name}\s*,
+ \s*#{attr_name}\s*,
+ #{rw},.*?\)\s*;%xm then
$1
- elsif @content =~ %r{Document-attr:\s#{attr_name}\s*?\n((?>.*?\*/))}m
+ elsif @content =~ %r%Document-attr:\s#{attr_name}\s*?\n
+ ((?>.*?\*/))%xm then
$1
else
''
@@ -280,8 +371,10 @@ class RDoc::Parser::C < RDoc::Parser
def find_body(class_name, meth_name, meth_obj, body, quiet = false)
case body
- when %r"((?>/\*.*?\*/\s*))((?:(?:static|SWIGINTERN)\s+)?(?:intern\s+)?VALUE\s+#{meth_name}
- \s*(\([^)]*\))([^;]|$))"xm
+ when %r%((?>/\*.*?\*/\s*))
+ ((?:(?:static|SWIGINTERN)\s+)?
+ (?:intern\s+)?VALUE\s+#{meth_name}
+ \s*(\([^)]*\))([^;]|$))%xm then
comment = $1
body_text = $2
@@ -303,12 +396,13 @@ class RDoc::Parser::C < RDoc::Parser
find_modifiers comment, meth_obj if comment
+ #meth_obj.params = params
meth_obj.start_collecting_tokens
tk = RDoc::RubyToken::Token.new nil, 1, 1
tk.set_text body_text
meth_obj.add_token tk
meth_obj.comment = strip_stars comment
- when %r{((?>/\*.*?\*/\s*))^\s*(\#\s*define\s+#{meth_name}\s+(\w+))}m
+ when %r%((?>/\*.*?\*/\s*))^\s*(\#\s*define\s+#{meth_name}\s+(\w+))%m
comment = $1
body_text = $2
find_body class_name, $3, meth_obj, body, true
@@ -319,26 +413,29 @@ class RDoc::Parser::C < RDoc::Parser
tk.set_text body_text
meth_obj.add_token tk
meth_obj.comment = strip_stars(comment) + meth_obj.comment.to_s
- when %r{^\s*\#\s*define\s+#{meth_name}\s+(\w+)}m
+ when %r%^\s*\#\s*define\s+#{meth_name}\s+(\w+)%m
unless find_body(class_name, $1, meth_obj, body, true)
- warn "No definition for #{meth_name}" unless @options.quiet
+ warn "No definition for #{meth_name}" if @options.verbosity > 1
return false
end
- else
- # No body, but might still have an override comment
- comment = find_override_comment(class_name, meth_obj.name)
+ else # No body, but might still have an override comment
+ comment = find_override_comment class_name, meth_obj.name
if comment
- find_modifiers(comment, meth_obj)
+ find_modifiers comment, meth_obj
meth_obj.comment = strip_stars comment
else
- warn "No definition for #{meth_name}" unless @options.quiet
+ warn "No definition for #{meth_name}" if @options.verbosity > 1
return false
end
end
+
true
end
+ ##
+ # Finds a RDoc::NormalClass or RDoc::NormalModule for +raw_name+
+
def find_class(raw_name, name)
unless @classes[raw_name]
if raw_name =~ /^rb_m/
@@ -382,16 +479,17 @@ class RDoc::Parser::C < RDoc::Parser
def find_class_comment(class_name, class_mod)
comment = nil
- if @content =~ %r{
+ if @content =~ %r%
((?>/\*.*?\*/\s+))
(static\s+)?
void\s+
- Init_#{class_name}\s*(?:_\(\s*)?\(\s*(?:void\s*)?\)}xmi then # )
- comment = $1
- elsif @content =~ %r{Document-(?:class|module):\s+#{class_name}\s*?(?:<\s+[:,\w]+)?\n((?>.*?\*/))}m then
+ Init_#{class_name}\s*(?:_\(\s*)?\(\s*(?:void\s*)?\)%xmi then
+ comment = $1.sub(%r%Document-(?:class|module):\s+#{class_name}%, '')
+ elsif @content =~ %r%Document-(?:class|module):\s+#{class_name}\s*?
+ (?:<\s+[:,\w]+)?\n((?>.*?\*/))%xm then
comment = $1
- elsif @content =~ %r{((?>/\*.*?\*/\s+))
- ([\w\.\s]+\s* = \s+)?rb_define_(class|module).*?"(#{class_name})"}xm then # "
+ elsif @content =~ %r%((?>/\*.*?\*/\s+))
+ ([\w\.\s]+\s* = \s+)?rb_define_(class|module).*?"(#{class_name})"%xm then
comment = $1
end
@@ -409,10 +507,13 @@ class RDoc::Parser::C < RDoc::Parser
# comment or in the matching Document- section.
def find_const_comment(type, const_name)
- if @content =~ %r{((?>^\s*/\*.*?\*/\s+))
- rb_define_#{type}\((?:\s*(\w+),)?\s*"#{const_name}"\s*,.*?\)\s*;}xmi
+ if @content =~ %r%((?>^\s*/\*.*?\*/\s+))
+ rb_define_#{type}\((?:\s*(\w+),)?\s*
+ "#{const_name}"\s*,
+ .*?\)\s*;%xmi then
$1
- elsif @content =~ %r{Document-(?:const|global|variable):\s#{const_name}\s*?\n((?>.*?\*/))}m
+ elsif @content =~ %r%Document-(?:const|global|variable):\s#{const_name}
+ \s*?\n((?>.*?\*/))%xm
$1
else
''
@@ -420,56 +521,111 @@ class RDoc::Parser::C < RDoc::Parser
end
##
- # If the comment block contains a section that looks like:
+ # Handles modifiers in +comment+ and updates +meth_obj+ as appropriate.
+ #
+ # If <tt>:nodoc:</tt> is found, documentation on +meth_obj+ is suppressed.
+ #
+ # If <tt>:yields:</tt> is followed by an argument list it is used for the
+ # #block_params of +meth_obj+.
+ #
+ # If the comment block contains a <tt>call-seq:</tt> section like:
+ #
+ # call-seq:
+ # ARGF.readlines(sep=$/) -> array
+ # ARGF.readlines(limit) -> array
+ # ARGF.readlines(sep, limit) -> array
#
- # call-seq:
- # Array.new
- # Array.new(10)
+ # ARGF.to_a(sep=$/) -> array
+ # ARGF.to_a(limit) -> array
+ # ARGF.to_a(sep, limit) -> array
#
- # use it for the parameters.
+ # it is used for the parameters of +meth_obj+.
+
+ def find_modifiers comment, meth_obj
+ # we must handle situations like the above followed by an unindented first
+ # comment. The difficulty is to make sure not to match lines starting
+ # with ARGF at the same indent, but that are after the first description
+ # paragraph.
+
+ if comment =~ /call-seq:(.*?[^\s\*].*?)^\s*\*?\s*$/m then
+ all_start, all_stop = $~.offset(0)
+ seq_start, seq_stop = $~.offset(1)
+
+ # we get the following lines that start with the leading word at the
+ # same indent, even if they have blank lines before
+ if $1 =~ /(^\s*\*?\s*\n)+^(\s*\*?\s*\w+)/m then
+ leading = $2 # ' * ARGF' in the example above
+ re = %r%
+ \A(
+ (^\s*\*?\s*\n)+
+ (^#{Regexp.escape leading}.*?\n)+
+ )+
+ ^\s*\*?\s*$
+ %xm
+ if comment[seq_stop..-1] =~ re then
+ all_stop = seq_stop + $~.offset(0).last
+ seq_stop = seq_stop + $~.offset(1).last
+ end
+ end
- def find_modifiers(comment, meth_obj)
- if comment.sub!(/:nodoc:\s*^\s*\*?\s*$/m, '') or
- comment.sub!(/\A\/\*\s*:nodoc:\s*\*\/\Z/, '')
- meth_obj.document_self = false
- end
- if comment.sub!(/call-seq:(.*?)^\s*\*?\s*$/m, '') or
- comment.sub!(/\A\/\*\s*call-seq:(.*?)\*\/\Z/, '')
- seq = $1
- seq.gsub!(/^\s*\*\s*/, '')
+ seq = comment[seq_start..seq_stop]
+ seq.gsub!(/^(\s*\*?\s*?)(\S|\n)/m, '\2')
+ comment.slice! all_start...all_stop
meth_obj.call_seq = seq
+ elsif comment.sub!(/\A\/\*\s*call-seq:(.*?)\*\/\Z/, '') then
+ meth_obj.call_seq = $1.strip
+ end
+
+ if comment.sub!(/\s*:(nodoc|doc|yields?|args?):\s*(.*)/, '') then
+ RDoc::Parser.process_directive meth_obj, $1, $2
end
end
+ ##
+ # Finds a <tt>Document-method</tt> override for +meth_name+ in +class_name+
+
def find_override_comment(class_name, meth_name)
name = Regexp.escape(meth_name)
- if @content =~ %r{Document-method:\s+#{class_name}(?:\.|::|#)#{name}\s*?\n((?>.*?\*/))}m then
+
+ if @content =~ %r%Document-method:\s+#{class_name}(?:\.|::|#)#{name}\s*?\n((?>.*?\*/))%m then
$1
- elsif @content =~ %r{Document-method:\s#{name}\s*?\n((?>.*?\*/))}m then
+ elsif @content =~ %r%Document-method:\s#{name}\s*?\n((?>.*?\*/))%m then
$1
end
end
- def handle_attr(var_name, attr_name, reader, writer)
+ ##
+ # Creates a new RDoc::Attr +attr_name+ on class +var_name+ that is either
+ # +read+, +write+ or both
+
+ def handle_attr(var_name, attr_name, read, write)
rw = ''
- rw << 'R' if reader
- rw << 'W' if writer
+ rw << 'R' if '1' == read
+ rw << 'W' if '1' == write
class_name = @known_classes[var_name]
return unless class_name
- class_obj = find_class(var_name, class_name)
+ class_obj = find_class var_name, class_name
+
+ return unless class_obj
- if class_obj
- comment = find_attr_comment(attr_name)
- comment = strip_stars comment
- att = RDoc::Attr.new '', attr_name, rw, comment
- @stats.add_method att
- class_obj.add_attribute(att)
- end
+ comment = find_attr_comment var_name, attr_name
+ comment = strip_stars comment
+
+ name = attr_name.gsub(/rb_intern\("([^"]+)"\)/, '\1')
+
+ attr = RDoc::Attr.new '', name, rw, comment
+
+ class_obj.add_attribute attr
+ @stats.add_attribute attr
end
+ ##
+ # Creates a new RDoc::NormalClass or RDoc::NormalModule based on +type+
+ # named +class_name+ in +parent+ which was assigned to the C +var_name+.
+
def handle_class_module(var_name, type, class_name, parent, in_module)
parent_name = @known_classes[parent] || parent
@@ -497,7 +653,7 @@ class RDoc::Parser::C < RDoc::Parser
class_name
end
- if @content =~ %r{Document-class:\s+#{full_name}\s*<\s+([:,\w]+)} then
+ if @content =~ %r%Document-class:\s+#{full_name}\s*<\s+([:,\w]+)% then
parent_name = $1
end
@@ -519,15 +675,14 @@ class RDoc::Parser::C < RDoc::Parser
end
##
- # Adds constant comments. By providing some_value: at the start ofthe
- # comment you can override the C value of the comment to give a friendly
- # definition.
+ # Adds constants. By providing some_value: at the start of the comment you
+ # can override the C value of the comment to give a friendly definition.
#
# /* 300: The perfect score in bowling */
# rb_define_const(cFoo, "PERFECT", INT2FIX(300);
#
- # Will override +INT2FIX(300)+ with the value +300+ in the output RDoc.
- # Values may include quotes and escaped colons (\:).
+ # Will override <tt>INT2FIX(300)</tt> with the value +300+ in the output
+ # RDoc. Values may include quotes and escaped colons (\:).
def handle_constants(type, var_name, const_name, definition)
class_name = @known_classes[var_name]
@@ -588,22 +743,35 @@ class RDoc::Parser::C < RDoc::Parser
body.gsub(/^#ifdef HAVE_PROTOTYPES.*?#else.*?\n(.*?)#endif.*?\n/m, '\1')
end
+ ##
+ # Adds an RDoc::AnyMethod +meth_name+ defined on a class or module assigned
+ # to +var_name+. +type+ is the type of method definition function used.
+ # +singleton_method+ and +module_function+ create a singleton method.
+
def handle_method(type, var_name, meth_name, meth_body, 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
+
return unless class_name
class_obj = find_class var_name, class_name
if class_obj then
- if meth_name == "initialize" then
- meth_name = "new"
- type = "singleton_method"
+ if meth_name == 'initialize' then
+ meth_name = 'new'
+ singleton = true
+ type = 'method' # force public
end
meth_obj = RDoc::AnyMethod.new '', meth_name
- meth_obj.singleton = %w[singleton_method module_function].include? type
+ meth_obj.singleton =
+ singleton || %w[singleton_method module_function].include?(type)
p_count = Integer(param_count) rescue -1
@@ -627,7 +795,8 @@ class RDoc::Parser::C < RDoc::Parser
body = @content
end
- if find_body(class_name, meth_body, meth_obj, body) and meth_obj.document_self then
+ if find_body(class_name, meth_body, meth_obj, body) and
+ meth_obj.document_self then
class_obj.add_method meth_obj
@stats.add_method meth_obj
meth_obj.visibility = :private if 'private_method' == type
@@ -635,13 +804,27 @@ class RDoc::Parser::C < RDoc::Parser
end
end
+ ##
+ # Registers a singleton class +sclass_var+ as a singleton of +class_var+
+
+ def handle_singleton sclass_var, class_var
+ class_name = @known_classes[class_var]
+
+ @singleton_classes[sclass_var] = class_name
+ end
+
+ ##
+ # Normalizes tabs in +body+
+
def handle_tab_width(body)
if /\t/ =~ body
tab_width = @options.tab_width
body.split(/\n/).map do |line|
- 1 while line.gsub!(/\t+/) { ' ' * (tab_width*$&.length - $`.length % tab_width)} && $~ #`
+ 1 while line.gsub!(/\t+/) do
+ ' ' * (tab_width * $&.length - $`.length % tab_width)
+ end && $~
line
- end .join("\n")
+ end.join "\n"
else
body
end
@@ -654,7 +837,7 @@ class RDoc::Parser::C < RDoc::Parser
# * :title: My Awesome Project
# */
#
- # This routine modifies it's parameter
+ # This routine modifies its parameter
def look_for_directives_in(context, comment)
preprocess = RDoc::Markup::PreProcess.new @file_name, @options.rdoc_include
@@ -665,29 +848,33 @@ class RDoc::Parser::C < RDoc::Parser
@options.main_page = param
''
when 'title' then
- @options.title = param
+ @options.default_title = param if @options.respond_to? :default_title=
''
end
end
comment
end
+
##
# Removes lines that are commented out that might otherwise get picked up
# when scanning for classes and methods
def remove_commented_out_lines
- @content.gsub!(%r{//.*rb_define_}, '//')
+ @content.gsub!(%r%//.*rb_define_%, '//')
end
+ ##
+ # Removes private comments from +comment+
+
def remove_private_comments(comment)
comment.gsub!(/\/?\*--\n(.*?)\/?\*\+\+/m, '')
comment.sub!(/\/?\*--\n.*/m, '')
end
##
- # Extract the classes/modules and methods from a C file and return the
- # corresponding top-level object
+ # Extracts the classes, modules, methods, attributes, constants and aliases
+ # from a C file and returns an RDoc::TopLevel for this file
def scan
remove_commented_out_lines
@@ -696,6 +883,7 @@ class RDoc::Parser::C < RDoc::Parser
do_methods
do_includes
do_aliases
+ do_attrs
@top_level
end
diff --git a/lib/rdoc/parser/perl.rb b/lib/rdoc/parser/perl.rb
deleted file mode 100644
index 0023a013a6..0000000000
--- a/lib/rdoc/parser/perl.rb
+++ /dev/null
@@ -1,165 +0,0 @@
-require 'rdoc/parser'
-
-##
-#
-# This is an attamept to write a basic parser for Perl's
-# POD (Plain old Documentation) format. Ruby code must
-# co-exist with Perl, and some tasks are easier in Perl
-# than Ruby because of existing libraries.
-#
-# One difficult is that Perl POD has no means of identifying
-# the classes (packages) and methods (subs) with which it
-# is associated, it is more like literate programming in so
-# far as it just happens to be in the same place as the code,
-# but need not be.
-#
-# We would like to support all the markup the POD provides
-# so that it will convert happily to HTML. At the moment
-# I don't think I can do that: time constraints.
-#
-
-class RDoc::Parser::PerlPOD < RDoc::Parser
-
- parse_files_matching(/.p[lm]$/)
-
- ##
- # Prepare to parse a perl file
-
- def initialize(top_level, file_name, content, options, stats)
- super
-
- preprocess = RDoc::Markup::PreProcess.new @file_name, @options.rdoc_include
-
- preprocess.handle @content do |directive, param|
- warn "Unrecognized directive '#{directive}' in #{@file_name}"
- end
- end
-
- ##
- # Extract the Pod(-like) comments from the code.
- # At its most basic there will ne no need to distinguish
- # between the different types of header, etc.
- #
- # This uses a simple finite state machine, in a very
- # procedural pattern. I could "replace case with polymorphism"
- # but I think it would obscure the intent, scatter the
- # code all over tha place. This machine is necessary
- # because POD requires that directives be preceded by
- # blank lines, so reading line by line is necessary,
- # and preserving state about what is seen is necesary.
-
- def scan
-
- @top_level.comment ||= ""
- state=:code_blank
- line_number = 0
- line = nil
-
- # This started out as a really long nested case statement,
- # which also led to repetitive code. I'd like to avoid that
- # so I'm using a "table" instead.
-
- # Firstly we need some procs to do the transition and processing
- # work. Because these are procs they are closures, and they can
- # use variables in the local scope.
- #
- # First, the "nothing to see here" stuff.
- code_noop = lambda do
- if line =~ /^\s+$/
- state = :code_blank
- end
- end
-
- pod_noop = lambda do
- if line =~ /^\s+$/
- state = :pod_blank
- end
- @top_level.comment += filter(line)
- end
-
- begin_noop = lambda do
- if line =~ /^\s+$/
- state = :begin_blank
- end
- @top_level.comment += filter(line)
- end
-
- # Now for the blocks that process code and comments...
-
- transit_to_pod = lambda do
- case line
- when /^=(?:pod|head\d+)/
- state = :pod_no_blank
- @top_level.comment += filter(line)
- when /^=over/
- state = :over_no_blank
- @top_level.comment += filter(line)
- when /^=(?:begin|for)/
- state = :begin_no_blank
- end
- end
-
- process_pod = lambda do
- case line
- when /^\s*$/
- state = :pod_blank
- @top_level.comment += filter(line)
- when /^=cut/
- state = :code_no_blank
- when /^=end/
- $stderr.puts "'=end' unexpected at #{line_number} in #{@file_name}"
- else
- @top_level.comment += filter(line)
- end
- end
-
-
- process_begin = lambda do
- case line
- when /^\s*$/
- state = :begin_blank
- @top_level.comment += filter(line)
- when /^=end/
- state = :code_no_blank
- when /^=cut/
- $stderr.puts "'=cut' unexpected at #{line_number} in #{@file_name}"
- else
- @top_level.comment += filter(line)
- end
-
- end
-
-
- transitions = { :code_no_blank => code_noop,
- :code_blank => transit_to_pod,
- :pod_no_blank => pod_noop,
- :pod_blank => process_pod,
- :begin_no_blank => begin_noop,
- :begin_blank => process_begin}
- @content.each_line do |l|
- line = l
- line_number += 1
- transitions[state].call
- end # each line
-
- @top_level
- end
-
- # Filter the perl markup that does the same as the rdoc
- # filtering. Only basic for now. Will probably need a
- # proper parser to cope with C<<...>> etc
- def filter(comment)
- return '' if comment =~ /^=pod\s*$/
- comment.gsub!(/^=pod/, '==')
- comment.gsub!(/^=head(\d+)/) do
- "=" * $1.to_i
- end
- comment.gsub!(/=item/, '');
- comment.gsub!(/C<(.*?)>/, '<tt>\1</tt>');
- comment.gsub!(/I<(.*?)>/, '<i>\1</i>');
- comment.gsub!(/B<(.*?)>/, '<b>\1</b>');
- comment
- end
-
-end
-
diff --git a/lib/rdoc/parser/ruby.rb b/lib/rdoc/parser/ruby.rb
index 2874c47a20..e6f07d66da 100644
--- a/lib/rdoc/parser/ruby.rb
+++ b/lib/rdoc/parser/ruby.rb
@@ -11,8 +11,8 @@ require 'rdoc/ruby_token'
require 'rdoc/ruby_lex'
require 'rdoc/code_objects'
-require 'rdoc/tokenstream'
-require 'rdoc/markup/preprocess'
+require 'rdoc/token_stream'
+require 'rdoc/markup/pre_process'
require 'rdoc/parser'
require 'rdoc/parser/ruby_tools'
@@ -162,6 +162,9 @@ class RDoc::Parser::Ruby < RDoc::Parser
SINGLE = "<<"
+ ##
+ # Creates a new Ruby parser.
+
def initialize(top_level, file_name, content, options, stats)
super
@@ -209,10 +212,13 @@ class RDoc::Parser::Ruby < RDoc::Parser
comment
end
+ ##
+ # Aborts with +msg+
+
def error(msg)
msg = make_message msg
- $stderr.puts msg
- exit false
+
+ abort msg
end
##
@@ -229,6 +235,10 @@ class RDoc::Parser::Ruby < RDoc::Parser
meth
end
+ ##
+ # Looks for a true or false token. Returns false if TkFALSE or TkNIL are
+ # found.
+
def get_bool
skip_tkspace
tk = get_tk
@@ -245,20 +255,24 @@ class RDoc::Parser::Ruby < RDoc::Parser
##
# Look for the name of a class of module (optionally with a leading :: or
- # with :: separated named) and return the ultimate name and container
+ # with :: separated named) and return the ultimate name, the associated
+ # container, and the given name (with the ::).
def get_class_or_module(container)
skip_tkspace
name_t = get_tk
+ given_name = ''
# class ::A -> A is in the top level
case name_t
when TkCOLON2, TkCOLON3 then # bug
name_t = get_tk
container = @top_level
+ given_name << '::'
end
skip_tkspace false
+ given_name << name_t.name
while TkCOLON2 === peek_tk do
prev_container = container
@@ -268,9 +282,10 @@ class RDoc::Parser::Ruby < RDoc::Parser
end
get_tk
name_t = get_tk
+ given_name << '::' << name_t.name
end
skip_tkspace false
- return [container, name_t]
+ return [container, name_t, given_name]
end
##
@@ -347,6 +362,9 @@ class RDoc::Parser::Ruby < RDoc::Parser
name
end
+ ##
+ # Extracts a name or symbol from the token stream.
+
def get_symbol_or_name
tk = get_tk
case tk
@@ -361,7 +379,10 @@ class RDoc::Parser::Ruby < RDoc::Parser
text
when TkId, TkOp then
tk.name
- when TkSTRING, TkDSTRING then
+ when TkAMPER,
+ TkDSTRING,
+ TkSTAR,
+ TkSTRING then
tk.text
else
raise RDoc::Error, "Name or symbol expected (got #{tk})"
@@ -374,7 +395,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
# # :stopdoc:
# # Don't display comment from this point forward
#
- # This routine modifies it's parameter
+ # This routine modifies its +comment+ parameter.
def look_for_directives_in(context, comment)
preprocess = RDoc::Markup::PreProcess.new @file_name, @options.rdoc_include
@@ -382,9 +403,10 @@ class RDoc::Parser::Ruby < RDoc::Parser
preprocess.handle comment, context do |directive, param|
case directive
when 'enddoc' then
- throw :enddoc
+ context.done_documenting = true
+ ''
when 'main' then
- @options.main_page = param
+ @options.main_page = param if @options.respond_to? :main_page
''
when 'method', 'singleton-method',
'attr', 'attr_accessor', 'attr_reader', 'attr_writer' then
@@ -401,7 +423,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
context.stop_doc
''
when 'title' then
- @options.title = param
+ @options.default_title = param if @options.respond_to? :default_title=
''
end
end
@@ -426,23 +448,28 @@ class RDoc::Parser::Ruby < RDoc::Parser
def parse_attr(context, single, tk, comment)
args = parse_symbol_arg 1
- if args.size > 0
+ if args.size > 0 then
name = args[0]
rw = "R"
skip_tkspace false
tk = get_tk
+
if TkCOMMA === tk then
rw = "RW" if get_bool
else
unget_tk tk
end
- att = RDoc::Attr.new get_tkread, name, rw, comment
+
+ att = RDoc::Attr.new get_tkread, name, rw, comment, single == SINGLE
+ att.record_location @top_level
+
read_documentation_modifiers att, RDoc::ATTR_MODIFIERS
- if att.document_self
- context.add_attribute(att)
- end
+
+ context.add_attribute att if att.document_self
+
+ @stats.add_attribute att
else
- warn("'attr' ignored - looks like a variable")
+ warn "'attr' ignored - looks like a variable"
end
end
@@ -452,12 +479,8 @@ class RDoc::Parser::Ruby < RDoc::Parser
def parse_attr_accessor(context, single, tk, comment)
args = parse_symbol_arg
- get_tkread
-
rw = "?"
- # TODO If nodoc is given, don't document any of them
-
tmp = RDoc::CodeObject.new
read_documentation_modifiers tmp, RDoc::ATTR_MODIFIERS
return unless tmp.document_self
@@ -471,17 +494,25 @@ class RDoc::Parser::Ruby < RDoc::Parser
end
for name in args
- att = RDoc::Attr.new get_tkread, name, rw, comment
+ att = RDoc::Attr.new get_tkread, name, rw, comment, single == SINGLE
+ att.record_location @top_level
+
context.add_attribute att
+ @stats.add_attribute att
end
end
+ ##
+ # Parses an +alias+ in +context+ with +comment+
+
def parse_alias(context, single, tk, comment)
skip_tkspace
+
if TkLPAREN === peek_tk then
get_tk
skip_tkspace
end
+
new_name = get_symbol_or_name
@scanner.instance_eval { @lex_state = EXPR_FNAME }
@@ -498,11 +529,20 @@ class RDoc::Parser::Ruby < RDoc::Parser
return
end
- al = RDoc::Alias.new get_tkread, old_name, new_name, comment
+ al = RDoc::Alias.new(get_tkread, old_name, new_name, comment,
+ single == SINGLE)
+ al.record_location @top_level
+
read_documentation_modifiers al, RDoc::ATTR_MODIFIERS
context.add_alias al if al.document_self
+ @stats.add_alias al
+
+ al
end
+ ##
+ # Extracts call parameters from the token stream.
+
def parse_call_parameters(tk)
end_token = case tk
when TkLPAREN, TkfLPAREN
@@ -540,28 +580,33 @@ class RDoc::Parser::Ruby < RDoc::Parser
res
end
+ ##
+ # Parses a class in +context+ with +comment+
+
def parse_class(container, single, tk, comment)
- container, name_t = get_class_or_module container
+ declaration_context = container
+ container, name_t, given_name = get_class_or_module container
case name_t
when TkCONSTANT
name = name_t.name
- superclass = "Object"
+ superclass = '::Object'
if TkLT === peek_tk then
get_tk
skip_tkspace
superclass = get_class_specification
- superclass = "<unknown>" if superclass.empty?
+ superclass = '(unknown)' if superclass.empty?
end
cls_type = single == SINGLE ? RDoc::SingleClass : RDoc::NormalClass
- cls = container.add_class cls_type, name, superclass
+ cls = declaration_context.add_class cls_type, given_name, superclass
read_documentation_modifiers cls, RDoc::CLASS_MODIFIERS
cls.record_location @top_level
- cls.comment = comment
+ cls.comment = comment if cls.document_self
+ @top_level.add_to_classes_or_modules cls
@stats.add_class cls
parse_statements cls
@@ -569,7 +614,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
case name = get_class_specification
when "self", container.name
parse_statements container, SINGLE
- when /\A[A-Z]/
+ else
other = RDoc::TopLevel.find_class_named name
unless other then
@@ -578,6 +623,15 @@ class RDoc::Parser::Ruby < RDoc::Parser
other.comment = comment
end
+ # notify :nodoc: all if not a constant-named class/module
+ # (and remove any comment)
+ unless name =~ /\A(::)?[A-Z]/
+ other.document_self = nil
+ other.document_children = false
+ other.clear_comment
+ end
+
+ @top_level.add_to_classes_or_modules other
@stats.add_class other
read_documentation_modifiers other, RDoc::CLASS_MODIFIERS
@@ -589,9 +643,15 @@ class RDoc::Parser::Ruby < RDoc::Parser
end
end
+ ##
+ # Parses a constant in +context+ with +comment+
+
def parse_constant(container, tk, comment)
name = tk.name
skip_tkspace false
+
+ return unless name =~ /^\w+$/
+
eq_tk = get_tk
unless TkASSIGN === eq_tk then
@@ -615,9 +675,9 @@ class RDoc::Parser::Ruby < RDoc::Parser
loop do
case tk
when TkSEMICOLON then
- break
- when TkLPAREN, TkfLPAREN, TkLBRACE, TkLBRACK, TkDO, TkIF, TkUNLESS,
- TkCASE then
+ break if nest <= 0
+ when TkLPAREN, TkfLPAREN, TkLBRACE, TkfLBRACE, TkLBRACK, TkfLBRACK,
+ TkDO, TkIF, TkUNLESS, TkCASE, TkDEF, TkBEGIN then
nest += 1
when TkRPAREN, TkRBRACE, TkRBRACK, TkEND then
nest -= 1
@@ -654,10 +714,11 @@ class RDoc::Parser::Ruby < RDoc::Parser
tk = get_tk
end
- res = get_tkread.tr("\n", " ").strip
+ res = get_tkread.gsub(/^[ \t]+/, '').strip
res = "" if res == ";"
con = RDoc::Constant.new name, res, comment
+ con.record_location @top_level
read_documentation_modifiers con, RDoc::CONSTANT_MODIFIERS
@stats.add_constant con
@@ -679,6 +740,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
name = $1 unless $1.empty?
meth = RDoc::GhostMethod.new get_tkread, name
+ meth.record_location @top_level
meth.singleton = singleton
meth.start_collecting_tokens
@@ -709,13 +771,19 @@ class RDoc::Parser::Ruby < RDoc::Parser
name = $3 unless $3.empty?
+ # TODO authorize 'singleton-attr...'?
att = RDoc::Attr.new get_tkread, name, rw, comment
+ att.record_location @top_level
+
container.add_attribute att
- @stats.add_method att
+ @stats.add_attribute att
end
end
+ ##
+ # Parses an +include+ in +context+ with +comment+
+
def parse_include(context, comment)
loop do
skip_tkspace_comment
@@ -759,8 +827,6 @@ class RDoc::Parser::Ruby < RDoc::Parser
def parse_meta_attr(context, single, tk, comment)
args = parse_symbol_arg
- get_tkread
-
rw = "?"
# If nodoc is given, don't document any of them
@@ -779,12 +845,19 @@ class RDoc::Parser::Ruby < RDoc::Parser
end
if name then
- att = RDoc::Attr.new get_tkread, name, rw, comment
+ att = RDoc::Attr.new get_tkread, name, rw, comment, single == SINGLE
+ att.record_location @top_level
+
context.add_attribute att
+ @stats.add_attribute att
else
args.each do |attr_name|
- att = RDoc::Attr.new get_tkread, attr_name, rw, comment
+ att = RDoc::Attr.new(get_tkread, attr_name, rw, comment,
+ single == SINGLE)
+ att.record_location @top_level
+
context.add_attribute att
+ @stats.add_attribute att
end
end
end
@@ -825,6 +898,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
end
meth = RDoc::MetaMethod.new get_tkread, name
+ meth.record_location @top_level
meth.singleton = singleton
remove_token_listener self
@@ -882,7 +956,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
token_listener self do
@scanner.instance_eval do @lex_state = EXPR_FNAME end
- skip_tkspace false
+ skip_tkspace
name_t = get_tk
back_tk = skip_tkspace
meth = nil
@@ -922,11 +996,17 @@ class RDoc::Parser::Ruby < RDoc::Parser
container.record_location @top_level
end
- when TkIDENTIFIER, TkIVAR then
+ when TkIDENTIFIER, TkIVAR, TkGVAR then
dummy = RDoc::Context.new
dummy.parent = container
skip_method dummy
return
+ when TkTRUE, TkFALSE, TkNIL then
+ klass_name = "#{name_t.name.capitalize}Class"
+ container = RDoc::TopLevel.find_class_named klass_name
+ container ||= @top_level.add_class RDoc::NormalClass, klass_name
+
+ name = name_t2.name
else
warn "unexpected method name token #{name_t.inspect}"
# break
@@ -959,6 +1039,8 @@ class RDoc::Parser::Ruby < RDoc::Parser
end
end
+ meth.record_location @top_level
+
meth.start_collecting_tokens
indent = TkSPACE.new nil, 1, 1
indent.set_text " " * column
@@ -1001,6 +1083,9 @@ class RDoc::Parser::Ruby < RDoc::Parser
@stats.add_method meth
end
+ ##
+ # Extracts +yield+ parameters from +method+
+
def parse_method_or_yield_parameters(method = nil,
modifiers = RDoc::METHOD_MODIFIERS)
skip_tkspace false
@@ -1024,14 +1109,16 @@ class RDoc::Parser::Ruby < RDoc::Parser
loop do
case tk
when TkSEMICOLON then
- break
- when TkLBRACE then
+ break if nest == 0
+ when TkLBRACE, TkfLBRACE then
nest += 1
when TkRBRACE then
- # we might have a.each {|i| yield i }
- unget_tk(tk) if nest.zero?
nest -= 1
- break if nest <= 0
+ if nest <= 0
+ # we might have a.each { |i| yield i }
+ unget_tk(tk) if nest < 0
+ break
+ end
when TkLPAREN, TkfLPAREN then
nest += 1
when end_token then
@@ -1041,6 +1128,8 @@ class RDoc::Parser::Ruby < RDoc::Parser
else
break unless @scanner.continue
end
+ when TkRPAREN then
+ nest -= 1
when method && method.block_params.nil? && TkCOMMENT then
unget_tk tk
read_documentation_modifiers method, modifiers
@@ -1078,8 +1167,11 @@ class RDoc::Parser::Ruby < RDoc::Parser
end
end
+ ##
+ # Parses an RDoc::NormalModule in +container+ with +comment+
+
def parse_module(container, single, tk, comment)
- container, name_t = get_class_or_module container
+ container, name_t, = get_class_or_module container
name = name_t.name
@@ -1087,12 +1179,16 @@ 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
parse_statements(mod)
- mod.comment = comment
+ @top_level.add_to_classes_or_modules mod
@stats.add_module mod
end
+ ##
+ # Parses an RDoc::Require in +context+ containing +comment+
+
def parse_require(context, comment)
skip_tkspace_comment
tk = get_tk
@@ -1105,7 +1201,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
name = tk.text if TkSTRING === tk
if name then
- context.add_require RDoc::Require.new(name, comment)
+ @top_level.add_require RDoc::Require.new(name, comment)
else
unget_tk tk
end
@@ -1206,7 +1302,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
# We can't solve the general case, but we can handle most occurrences by
# ignoring a do at the end of a line.
- when TkUNTIL, TkWHILE then
+ when TkUNTIL, TkWHILE then
nest += 1
skip_optional_do_after_expression
@@ -1275,9 +1371,14 @@ class RDoc::Parser::Ruby < RDoc::Parser
end
end
+ ##
+ # Parse up to +no+ symbol arguments
+
def parse_symbol_arg(no = nil)
args = []
+
skip_tkspace_comment
+
case tk = get_tk
when TkLPAREN
loop do
@@ -1320,28 +1421,40 @@ class RDoc::Parser::Ruby < RDoc::Parser
end
end
end
+
args
end
+ ##
+ # Returns symbol text from the next token
+
def parse_symbol_in_arg
case tk = get_tk
when TkSYMBOL
tk.text.sub(/^:/, '')
when TkSTRING
eval @read[-1]
+ when TkDSTRING, TkIDENTIFIER then
+ nil # ignore
else
warn("Expected symbol or string, got #{tk.inspect}") if $DEBUG_RDOC
nil
end
end
+ ##
+ # Parses statements at the toplevel in +container+
+
def parse_top_level_statements(container)
comment = collect_first_comment
look_for_directives_in(container, comment)
- container.comment = comment unless comment.empty?
+ container.comment = comment if container.document_self unless comment.empty?
parse_statements container, NORMAL, nil, comment
end
+ ##
+ # Determines the visibility in +container+ from +tk+
+
def parse_visibility(container, single, tk)
singleton = (single == SINGLE)
@@ -1383,7 +1496,8 @@ class RDoc::Parser::Ruby < RDoc::Parser
container.methods_matching args do |m|
s_m = m.dup
- s_m.singleton = true if RDoc::AnyMethod === s_m
+ s_m.record_location @top_level
+ s_m.singleton = true
s_m.visibility = :public
module_functions << s_m
end
@@ -1403,6 +1517,9 @@ class RDoc::Parser::Ruby < RDoc::Parser
end
end
+ ##
+ # Determines the block parameter for +context+
+
def parse_yield(context, single, tk, method)
return if method.block_params
@@ -1423,93 +1540,81 @@ class RDoc::Parser::Ruby < RDoc::Parser
#
# We return the directive name and any parameters as a two element array
- def read_directive(allowed)
+ def read_directive allowed
tk = get_tk
- result = nil
if TkCOMMENT === tk then
- if tk.text =~ /\s*:?(\w+):\s*(.*)/ then
- directive = $1.downcase
- if allowed.include? directive then
- result = [directive, $2]
- end
- end
+ return unless tk.text =~ /\s*:?(\w+):\s*(.*)/
+
+ directive = $1.downcase
+
+ return [directive, $2] if allowed.include? directive
else
unget_tk tk
end
-
- result
end
- def read_documentation_modifiers(context, allow)
- dir = read_directive(allow)
-
- case dir[0]
- when "notnew", "not_new", "not-new" then
- context.dont_rename_initialize = true
-
- when "nodoc" then
- context.document_self = false
- if dir[1].downcase == "all"
- context.document_children = false
- end
-
- when "doc" then
- context.document_self = true
- context.force_documentation = true
+ ##
+ # Handles the directive for +context+ if the directive is listed in +allow+.
+ # This method is called for directives following a definition.
- when "yield", "yields" then
- unless context.params.nil?
- context.params.sub!(/(,|)\s*&\w+/,'') # remove parameter &proc
- end
+ def read_documentation_modifiers(context, allow)
+ directive, value = read_directive allow
- context.block_params = dir[1]
+ return unless directive
- when "arg", "args" then
- context.params = dir[1]
- end if dir
+ case directive
+ when 'notnew', 'not_new', 'not-new' then
+ context.dont_rename_initialize = true
+ else
+ RDoc::Parser.process_directive context, directive, value
+ end
end
+ ##
+ # Removes private comments from +comment+
+
def remove_private_comments(comment)
- comment.gsub!(/^#--\n.*?^#\+\+/m, '')
- comment.sub!(/^#--\n.*/m, '')
+ comment.gsub!(/^#--\n.*?^#\+\+\n?/m, '')
+ comment.sub!(/^#--\n.*\n?/m, '')
end
+ ##
+ # Scans this ruby file for ruby constructs
+
def scan
reset
catch :eof do
- catch :enddoc do
- begin
- parse_top_level_statements @top_level
- rescue StandardError => e
- bytes = ''
-
- 20.times do @scanner.ungetc end
- count = 0
- 60.times do |i|
- count = i
- byte = @scanner.getc
- break unless byte
- bytes << byte
- end
- count -= 20
- count.times do @scanner.ungetc end
+ begin
+ parse_top_level_statements @top_level
+ rescue StandardError => e
+ bytes = ''
+
+ 20.times do @scanner.ungetc end
+ count = 0
+ 60.times do |i|
+ count = i
+ byte = @scanner.getc
+ break unless byte
+ bytes << byte
+ end
+ count -= 20
+ count.times do @scanner.ungetc end
- $stderr.puts <<-EOF
+ $stderr.puts <<-EOF
#{self.class} failure around line #{@scanner.line_no} of
#{@file_name}
- EOF
+ EOF
- unless bytes.empty? then
- $stderr.puts
- $stderr.puts bytes.inspect
- end
-
- raise e
+ unless bytes.empty? then
+ $stderr.puts
+ $stderr.puts bytes.inspect
end
+
+ raise e
end
end
@@ -1574,6 +1679,9 @@ class RDoc::Parser::Ruby < RDoc::Parser
unget_tk(tk) unless TkIN === tk
end
+ ##
+ # Skips the next method in +container+
+
def skip_method container
meth = RDoc::AnyMethod.new "", "anon"
parse_method_parameters meth
@@ -1591,6 +1699,9 @@ class RDoc::Parser::Ruby < RDoc::Parser
end
end
+ ##
+ # Prints +msg+ to +$stderr+ unless we're being quiet
+
def warn(msg)
return if @options.quiet
msg = make_message msg
diff --git a/lib/rdoc/parser/ruby_tools.rb b/lib/rdoc/parser/ruby_tools.rb
index 90c03307b4..3f6190884e 100644
--- a/lib/rdoc/parser/ruby_tools.rb
+++ b/lib/rdoc/parser/ruby_tools.rb
@@ -49,7 +49,6 @@ module RDoc::Parser::RubyTools
obj.pop_token
end if @token_listeners
else
- warn("':' not followed by identifier or operator")
tk = tk1
end
end
@@ -62,6 +61,10 @@ module RDoc::Parser::RubyTools
tk
end
+ ##
+ # Reads and returns all tokens up to one of +tokens+. Leaves the matched
+ # token in the token list.
+
def get_tk_until(*tokens)
read = []
diff --git a/lib/rdoc/parser/simple.rb b/lib/rdoc/parser/simple.rb
index e99d2d4319..1e82eb5097 100644
--- a/lib/rdoc/parser/simple.rb
+++ b/lib/rdoc/parser/simple.rb
@@ -1,7 +1,6 @@
##
# Parse a non-source file. We basically take the whole thing as one big
-# comment. If the first character in the file is '#', we strip leading pound
-# signs.
+# comment.
class RDoc::Parser::Simple < RDoc::Parser
@@ -32,10 +31,16 @@ class RDoc::Parser::Simple < RDoc::Parser
@top_level
end
- def remove_private_comments(comment)
- comment.gsub(/^--\n.*?^\+\+/m, '').sub(/^--\n.*/m, '')
+ ##
+ # Removes comments wrapped in <tt>--/++</tt>
+
+ def remove_private_comments text
+ text.gsub(/^--\n.*?^\+\+/m, '').sub(/^--\n.*/m, '')
end
+ ##
+ # Removes the encoding magic comment from +text+
+
def remove_coding_comment text
text.sub(/\A# .*coding[=:].*$/, '')
end