aboutsummaryrefslogtreecommitdiffstats
path: root/lib/rdoc/parser/c.rb
diff options
context:
space:
mode:
authordrbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2011-02-02 00:32:30 +0000
committerdrbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2011-02-02 00:32:30 +0000
commitcc2a16d94d744d14d4a5eb06eca22137f8a9b79e (patch)
tree2907a20e2d9ae3a2831707056bb3fe2d384b066d /lib/rdoc/parser/c.rb
parent918f625a5eeba35b9b191cb39c1d634b4cc7efee (diff)
downloadruby-cc2a16d94d744d14d4a5eb06eca22137f8a9b79e.tar.gz
Import RDoc 3.5.1
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@30760 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/rdoc/parser/c.rb')
-rw-r--r--lib/rdoc/parser/c.rb194
1 files changed, 150 insertions, 44 deletions
diff --git a/lib/rdoc/parser/c.rb b/lib/rdoc/parser/c.rb
index db37985b6d..bb015690bd 100644
--- a/lib/rdoc/parser/c.rb
+++ b/lib/rdoc/parser/c.rb
@@ -71,7 +71,7 @@ require 'rdoc/known_classes'
# 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,
+# Because C source doesn't give descriptive names to Ruby-level parameters,
# you need to document the calling sequence explicitly
#
# In addition, RDoc assumes by default that the C method implementing a
@@ -156,6 +156,7 @@ class RDoc::Parser::C < RDoc::Parser
comment = strip_stars comment
al.comment = comment
+ al.record_location @top_level
class_obj.add_alias al
@stats.add_alias al
end
@@ -284,7 +285,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, function, param_count, source_file|
# Ignore top-object and weird struct.c dynamic stuff
next if var_name == "ruby_top_self"
@@ -293,7 +294,7 @@ class RDoc::Parser::C < RDoc::Parser
next if var_name == "argf" # it'd be nice to handle this one
var_name = "rb_cObject" if var_name == "rb_mKernel"
- handle_method(type, var_name, meth_name, meth_body, param_count,
+ handle_method(type, var_name, meth_name, function, param_count,
source_file)
end
@@ -302,18 +303,19 @@ class RDoc::Parser::C < RDoc::Parser
\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|
- handle_method("method", "rb_mKernel", meth_name,
- meth_body, param_count, source_file)
+ %xm) do |meth_name, function, param_count, source_file|
+ handle_method("method", "rb_mKernel", meth_name, function, 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*(-?\w+)\s*\)/xm) do |meth_name, function, 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)
+ handle_method("method", "rb_mFileTest", meth_name, function, param_count)
+ handle_method("singleton_method", "rb_cFile", meth_name, function,
+ param_count)
end
end
@@ -369,21 +371,20 @@ class RDoc::Parser::C < RDoc::Parser
##
# Find the C code corresponding to a Ruby method
- def find_body(class_name, meth_name, meth_obj, body, quiet = false)
- case body
+ def find_body class_name, meth_name, meth_obj, file_content, quiet = false
+ case file_content
when %r%((?>/\*.*?\*/\s*)?)
((?:(?:static|SWIGINTERN)\s+)?
(?:intern\s+)?VALUE\s+#{meth_name}
- \s*(\([^)]*\))([^;]|$))%xm then
+ \s*(\(.*?\))([^;]|$))%xm then
comment = $1
- body_text = $2
+ body = $2
+ offset = $~.offset(2).first
remove_private_comments comment if comment
- # see if we can find the whole body
-
- re = Regexp.escape(body_text) + '[^(]*^\{.*?^\}'
- body_text = $& if /#{re}/m =~ body
+ # try to find the whole body
+ body = $& if /#{Regexp.escape body}[^(]*?\{.*?^\}/m =~ file_content
# The comment block may have been overridden with a 'Document-method'
# block. This happens in the interpreter when multiple methods are
@@ -399,38 +400,53 @@ class RDoc::Parser::C < RDoc::Parser
#meth_obj.params = params
meth_obj.start_collecting_tokens
tk = RDoc::RubyToken::Token.new nil, 1, 1
- tk.set_text body_text
+ tk.set_text body
meth_obj.add_token tk
meth_obj.comment = strip_stars comment
- when %r%((?>/\*.*?\*/\s*))^\s*(\#\s*define\s+#{meth_name}\s+(\w+))%m
+ meth_obj.offset = offset
+ meth_obj.line = file_content[0, offset].count("\n") + 1
+
+ body
+ when %r%((?>/\*.*?\*/\s*))^\s*(\#\s*define\s+#{meth_name}\s+(\w+))%m then
comment = $1
- body_text = $2
- find_body class_name, $3, meth_obj, body, true
+ body = $2
+ offset = $~.offset(2).first
+
+ find_body class_name, $3, meth_obj, file_content, true
find_modifiers comment, meth_obj
meth_obj.start_collecting_tokens
tk = RDoc::RubyToken::Token.new nil, 1, 1
- tk.set_text body_text
+ tk.set_text body
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
- unless find_body(class_name, $1, meth_obj, body, true)
- warn "No definition for #{meth_name}" if @options.verbosity > 1
- return false
- end
+ meth_obj.offset = offset
+ meth_obj.line = file_content[0, offset].count("\n") + 1
+
+ body
+ when %r%^\s*\#\s*define\s+#{meth_name}\s+(\w+)%m then
+ # with no comment we hope the aliased definition has it and use it's
+ # definition
+
+ body = find_body(class_name, $1, meth_obj, file_content, true)
+
+ return body if body
+
+ warn "No definition for #{meth_name}" if @options.verbosity > 1
+ false
else # No body, but might still have an override comment
comment = find_override_comment class_name, meth_obj.name
- if comment
+ if comment then
find_modifiers comment, meth_obj
meth_obj.comment = strip_stars comment
+
+ ''
else
warn "No definition for #{meth_name}" if @options.verbosity > 1
- return false
+ false
end
end
-
- true
end
##
@@ -618,6 +634,7 @@ class RDoc::Parser::C < RDoc::Parser
attr = RDoc::Attr.new '', name, rw, comment
+ attr.record_location @top_level
class_obj.add_attribute attr
@stats.add_attribute attr
end
@@ -732,6 +749,7 @@ class RDoc::Parser::C < RDoc::Parser
con = RDoc::Constant.new const_name, definition, comment
end
+ con.record_location @top_level
@stats.add_constant con
class_obj.add_constant con
end
@@ -748,7 +766,7 @@ class RDoc::Parser::C < RDoc::Parser
# 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,
+ def handle_method(type, var_name, meth_name, function, param_count,
source_file = nil)
singleton = false
class_name = @known_classes[var_name]
@@ -770,33 +788,37 @@ class RDoc::Parser::C < RDoc::Parser
end
meth_obj = RDoc::AnyMethod.new '', meth_name
+ meth_obj.c_function = function
meth_obj.singleton =
singleton || %w[singleton_method module_function].include?(type)
p_count = Integer(param_count) rescue -1
- if p_count < 0 then
- meth_obj.params = "(...)"
- elsif p_count == 0
- meth_obj.params = "()"
- else
- meth_obj.params = "(" + (1..p_count).map{|i| "p#{i}"}.join(", ") + ")"
- end
-
if source_file then
file_name = File.join @file_dir, source_file
if File.exist? file_name then
- body = (@@known_bodies[file_name] ||= File.read(file_name))
+ file_content = (@@known_bodies[file_name] ||= File.read(file_name))
else
warn "unknown source #{source_file} for #{meth_name} in #{@file_name}"
end
else
- body = @content
+ file_content = @content
end
- if find_body(class_name, meth_body, meth_obj, body) and
- meth_obj.document_self then
+ body = find_body class_name, function, meth_obj, file_content
+
+ if body and meth_obj.document_self then
+ meth_obj.params = if p_count < -1 then # -2 is Array
+ '(*args)'
+ elsif p_count == -1 then # argc, argv
+ rb_scan_args body
+ else
+ "(#{(1..p_count).map { |i| "p#{i}" }.join ', '})"
+ end
+
+
+ meth_obj.record_location @top_level
class_obj.add_method meth_obj
@stats.add_method meth_obj
meth_obj.visibility = :private if 'private_method' == type
@@ -857,6 +879,90 @@ class RDoc::Parser::C < RDoc::Parser
end
##
+ # Extracts parameters from the +method_body+ and returns a method
+ # parameter string. Follows 1.9.3dev's scan-arg-spec, see README.EXT
+
+ def rb_scan_args method_body
+ method_body =~ /rb_scan_args\((.*?)\)/m
+ return '(*args)' unless $1
+
+ $1.split(/,/)[2] =~ /"(.*?)"/ # format argument
+ format = $1.split(//)
+
+ lead = opt = trail = 0
+
+ if format.first =~ /\d/ then
+ lead = $&.to_i
+ format.shift
+ if format.first =~ /\d/ then
+ opt = $&.to_i
+ format.shift
+ if format.first =~ /\d/ then
+ trail = $&.to_i
+ format.shift
+ block_arg = true
+ end
+ end
+ end
+
+ if format.first == '*' and not block_arg then
+ var = true
+ format.shift
+ if format.first =~ /\d/ then
+ trail = $&.to_i
+ format.shift
+ end
+ end
+
+ if format.first == ':' then
+ hash = true
+ format.shift
+ end
+
+ if format.first == '&' then
+ block = true
+ format.shift
+ end
+
+ # if the format string is not empty there's a bug in the C code, ignore it
+
+ args = []
+ position = 1
+
+ (1...(position + lead)).each do |index|
+ args << "p#{index}"
+ end
+
+ position += lead
+
+ (position...(position + opt)).each do |index|
+ args << "p#{index} = v#{index}"
+ end
+
+ position += opt
+
+ if var then
+ args << '*args'
+ position += 1
+ end
+
+ (position...(position + trail)).each do |index|
+ args << "p#{index}"
+ end
+
+ position += trail
+
+ if hash then
+ args << "p#{position} = {}"
+ position += 1
+ end
+
+ args << '&block' if block
+
+ "(#{args.join ', '})"
+ end
+
+ ##
# Removes lines that are commented out that might otherwise get picked up
# when scanning for classes and methods