summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog18
-rw-r--r--ext/bigdecimal/bigdecimal.c68
-rw-r--r--lib/rdoc/parsers/parse_c.rb226
-rw-r--r--test/rdoc/parsers/test_parse_c.rb148
4 files changed, 342 insertions, 118 deletions
diff --git a/ChangeLog b/ChangeLog
index 0230ef6bd6..bca7f193bf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+Mon Jan 1 06:13:11 2007 Eric Hodel <drbrain@segment7.net>
+
+ * lib/rdoc/parsers/c_parser.rb: Make Rdoc accessible. Update constant
+ value information.
+
+Mon Jan 1 06:13:11 2007 Eric Hodel <drbrain@segment7.net>
+
+ * ext/bigdecimal/bigdecimal.c: Update constant comments to provide
+ values for RDoc.
+
+Mon Jan 1 06:05:55 2007 Eric Hodel <drbrain@segment7.net>
+
+ * lib/rdoc/parsers/parse_c.rb (RDoc::C_Parser#handle_constansts):
+ Allow RDoc comment to give friendly value for rb_define_const. Patch
+ by Daniel Berger <djberg96 at gmail.com>, [ruby-patches-7499].
+ * lib/rdoc/parsers/parse_c.rb (RDoc::C_Parser#handle_constansts): Fix
+ whitespace handling in constant comments.
+
Sun Dec 31 00:31:16 2006 Tadayoshi Funaba <tadf@dotrb.org>
* lib/date.rb, lib/date/format.rb: updated based on date2 4.0.
diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c
index f10af59f5b..370f5ecd50 100644
--- a/ext/bigdecimal/bigdecimal.c
+++ b/ext/bigdecimal/bigdecimal.c
@@ -1811,76 +1811,94 @@ Init_bigdecimal(void)
/* Exceptions */
/*
- * Determines whether overflow, underflow or zero divide result in
+ * 0xff: Determines whether overflow, underflow or zero divide result in
* an exception being thrown. See BigDecimal.mode.
*/
rb_define_const(rb_cBigDecimal, "EXCEPTION_ALL",INT2FIX(VP_EXCEPTION_ALL));
/*
- * Determines what happens when the result of a computation is not a
+ * 0x02: Determines what happens when the result of a computation is not a
* number (NaN). See BigDecimal.mode.
*/
rb_define_const(rb_cBigDecimal, "EXCEPTION_NaN",INT2FIX(VP_EXCEPTION_NaN));
/*
- * Determines what happens when the result of a computation is infinity.
- * See BigDecimal.mode.
+ * 0x01: Determines what happens when the result of a computation is
+ * infinity. See BigDecimal.mode.
*/
rb_define_const(rb_cBigDecimal, "EXCEPTION_INFINITY",INT2FIX(VP_EXCEPTION_INFINITY));
/*
- * Determines what happens when the result of a computation is an underflow
- * (a result too small to be represented). See BigDecimal.mode.
+ * 0x04: Determines what happens when the result of a computation is an
+ * underflow (a result too small to be represented). See BigDecimal.mode.
*/
rb_define_const(rb_cBigDecimal, "EXCEPTION_UNDERFLOW",INT2FIX(VP_EXCEPTION_UNDERFLOW));
/*
- * Determines what happens when the result of a computation is an underflow
- * (a result too large to be represented). See BigDecimal.mode.
+ * 0x01: Determines what happens when the result of a computation is an
+ * underflow (a result too large to be represented). See BigDecimal.mode.
*/
rb_define_const(rb_cBigDecimal, "EXCEPTION_OVERFLOW",INT2FIX(VP_EXCEPTION_OVERFLOW));
/*
- * Determines what happens when a division by zero is performed.
+ * 0x01: Determines what happens when a division by zero is performed.
* See BigDecimal.mode.
*/
rb_define_const(rb_cBigDecimal, "EXCEPTION_ZERODIVIDE",INT2FIX(VP_EXCEPTION_ZERODIVIDE));
/*
- * Determines what happens when a result must be rounded in order to
- * fit in the appropriate number of significant digits. See
+ * 0x100: Determines what happens when a result must be rounded in order to
+ * fit in the appropriate number of significant digits. See
* BigDecimal.mode.
*/
rb_define_const(rb_cBigDecimal, "ROUND_MODE",INT2FIX(VP_ROUND_MODE));
- /* Indicates that values should be rounded away from zero. See BigDecimal.mode. */
+ /* 1: Indicates that values should be rounded away from zero. See
+ * BigDecimal.mode.
+ */
rb_define_const(rb_cBigDecimal, "ROUND_UP",INT2FIX(VP_ROUND_UP));
- /* Indicates that values should be rounded towards zero. See BigDecimal.mode. */
+
+ /* 2: Indicates that values should be rounded towards zero. See
+ * BigDecimal.mode.
+ */
rb_define_const(rb_cBigDecimal, "ROUND_DOWN",INT2FIX(VP_ROUND_DOWN));
- /* Indicates that digits >= 5 should be rounded up, others rounded down. See BigDecimal.mode. */
+
+ /* 3: Indicates that digits >= 5 should be rounded up, others rounded down.
+ * See BigDecimal.mode. */
rb_define_const(rb_cBigDecimal, "ROUND_HALF_UP",INT2FIX(VP_ROUND_HALF_UP));
- /* Indicates that digits >= 6 should be rounded up, others rounded down. See BigDecimal.mode. */
+
+ /* 4: Indicates that digits >= 6 should be rounded up, others rounded down.
+ * See BigDecimal.mode.
+ */
rb_define_const(rb_cBigDecimal, "ROUND_HALF_DOWN",INT2FIX(VP_ROUND_HALF_DOWN));
- /* Round towards +infinity. See BigDecimal.mode. */
+ /* 5: Round towards +infinity. See BigDecimal.mode. */
rb_define_const(rb_cBigDecimal, "ROUND_CEILING",INT2FIX(VP_ROUND_CEIL));
- /* Round towards -infinity. See BigDecimal.mode. */
+
+ /* 6: Round towards -infinity. See BigDecimal.mode. */
rb_define_const(rb_cBigDecimal, "ROUND_FLOOR",INT2FIX(VP_ROUND_FLOOR));
- /* Round towards the even neighbor. See BigDecimal.mode. */
+
+ /* 7: Round towards the even neighbor. See BigDecimal.mode. */
rb_define_const(rb_cBigDecimal, "ROUND_HALF_EVEN",INT2FIX(VP_ROUND_HALF_EVEN));
- /* Indicates that a value is not a number. See BigDecimal.sign. */
+ /* 0: Indicates that a value is not a number. See BigDecimal.sign. */
rb_define_const(rb_cBigDecimal, "SIGN_NaN",INT2FIX(VP_SIGN_NaN));
- /* Indicates that a value is +0. See BigDecimal.sign. */
+
+ /* 1: Indicates that a value is +0. See BigDecimal.sign. */
rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_ZERO",INT2FIX(VP_SIGN_POSITIVE_ZERO));
- /* Indicates that a value is -0. See BigDecimal.sign. */
+
+ /* -1: Indicates that a value is -0. See BigDecimal.sign. */
rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_ZERO",INT2FIX(VP_SIGN_NEGATIVE_ZERO));
- /* Indicates that a value is positive and finite. See BigDecimal.sign. */
+
+ /* 2: Indicates that a value is positive and finite. See BigDecimal.sign. */
rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_FINITE",INT2FIX(VP_SIGN_POSITIVE_FINITE));
- /* Indicates that a value is negative and finite. See BigDecimal.sign. */
+
+ /* -2: Indicates that a value is negative and finite. See BigDecimal.sign. */
rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_FINITE",INT2FIX(VP_SIGN_NEGATIVE_FINITE));
- /* Indicates that a value is positive and infinite. See BigDecimal.sign. */
+
+ /* 3: Indicates that a value is positive and infinite. See BigDecimal.sign. */
rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_INFINITE",INT2FIX(VP_SIGN_POSITIVE_INFINITE));
- /* Indicates that a value is negative and infinite. See BigDecimal.sign. */
+
+ /* -3: Indicates that a value is negative and infinite. See BigDecimal.sign. */
rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_INFINITE",INT2FIX(VP_SIGN_NEGATIVE_INFINITE));
/* instance methods */
diff --git a/lib/rdoc/parsers/parse_c.rb b/lib/rdoc/parsers/parse_c.rb
index 19b5d443f6..4ebd25c709 100644
--- a/lib/rdoc/parsers/parse_c.rb
+++ b/lib/rdoc/parsers/parse_c.rb
@@ -1,3 +1,78 @@
+# Classes and modules built in to the interpreter. We need
+# these to define superclasses of user objects
+
+require "rdoc/code_objects"
+require "rdoc/parsers/parserfactory"
+require "rdoc/options"
+require "rdoc/rdoc"
+
+module RDoc
+
+ ##
+ # Ruby's built-in classes.
+
+ KNOWN_CLASSES = {
+ "rb_cObject" => "Object",
+ "rb_cArray" => "Array",
+ "rb_cBignum" => "Bignum",
+ "rb_cClass" => "Class",
+ "rb_cDir" => "Dir",
+ "rb_cData" => "Data",
+ "rb_cFalseClass" => "FalseClass",
+ "rb_cFile" => "File",
+ "rb_cFixnum" => "Fixnum",
+ "rb_cFloat" => "Float",
+ "rb_cHash" => "Hash",
+ "rb_cInteger" => "Integer",
+ "rb_cIO" => "IO",
+ "rb_cModule" => "Module",
+ "rb_cNilClass" => "NilClass",
+ "rb_cNumeric" => "Numeric",
+ "rb_cProc" => "Proc",
+ "rb_cRange" => "Range",
+ "rb_cRegexp" => "Regexp",
+ "rb_cString" => "String",
+ "rb_cSymbol" => "Symbol",
+ "rb_cThread" => "Thread",
+ "rb_cTime" => "Time",
+ "rb_cTrueClass" => "TrueClass",
+ "rb_cStruct" => "Struct",
+ "rb_eException" => "Exception",
+ "rb_eStandardError" => "StandardError",
+ "rb_eSystemExit" => "SystemExit",
+ "rb_eInterrupt" => "Interrupt",
+ "rb_eSignal" => "Signal",
+ "rb_eFatal" => "Fatal",
+ "rb_eArgError" => "ArgError",
+ "rb_eEOFError" => "EOFError",
+ "rb_eIndexError" => "IndexError",
+ "rb_eRangeError" => "RangeError",
+ "rb_eIOError" => "IOError",
+ "rb_eRuntimeError" => "RuntimeError",
+ "rb_eSecurityError" => "SecurityError",
+ "rb_eSystemCallError" => "SystemCallError",
+ "rb_eTypeError" => "TypeError",
+ "rb_eZeroDivError" => "ZeroDivError",
+ "rb_eNotImpError" => "NotImpError",
+ "rb_eNoMemError" => "NoMemError",
+ "rb_eFloatDomainError" => "FloatDomainError",
+ "rb_eScriptError" => "ScriptError",
+ "rb_eNameError" => "NameError",
+ "rb_eSyntaxError" => "SyntaxError",
+ "rb_eLoadError" => "LoadError",
+
+ "rb_mKernel" => "Kernel",
+ "rb_mComparable" => "Comparable",
+ "rb_mEnumerable" => "Enumerable",
+ "rb_mPrecision" => "Precision",
+ "rb_mErrno" => "Errno",
+ "rb_mFileTest" => "FileTest",
+ "rb_mGC" => "GC",
+ "rb_mMath" => "Math",
+ "rb_mProcess" => "Process"
+ }
+
+ ##
# We attempt to parse C extension files. Basically we look 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
@@ -52,8 +127,8 @@
# when the <tt>Init_xxx</tt> method is not named after the class.
#
# [Document-method: <i>name</i>]
- # This comment documents the named method. Use when RDoc cannot outomatically
- # find the method from it's declaration
+ # This comment documents the named method. Use when RDoc cannot
+ # automatically find the method from it's declaration
#
# [call-seq: <i>text up to an empty line</i>]
# Because C source doesn't give descripive names to Ruby-level parameters,
@@ -89,82 +164,9 @@
# */
#
-
- # Classes and modules built in to the interpreter. We need
- # these to define superclasses of user objects
-
-require "rdoc/code_objects"
-require "rdoc/parsers/parserfactory"
-
-
-module RDoc
-
- KNOWN_CLASSES = {
- "rb_cObject" => "Object",
- "rb_cArray" => "Array",
- "rb_cBignum" => "Bignum",
- "rb_cClass" => "Class",
- "rb_cDir" => "Dir",
- "rb_cData" => "Data",
- "rb_cFalseClass" => "FalseClass",
- "rb_cFile" => "File",
- "rb_cFixnum" => "Fixnum",
- "rb_cFloat" => "Float",
- "rb_cHash" => "Hash",
- "rb_cInteger" => "Integer",
- "rb_cIO" => "IO",
- "rb_cModule" => "Module",
- "rb_cNilClass" => "NilClass",
- "rb_cNumeric" => "Numeric",
- "rb_cProc" => "Proc",
- "rb_cRange" => "Range",
- "rb_cRegexp" => "Regexp",
- "rb_cString" => "String",
- "rb_cSymbol" => "Symbol",
- "rb_cThread" => "Thread",
- "rb_cTime" => "Time",
- "rb_cTrueClass" => "TrueClass",
- "rb_cStruct" => "Struct",
- "rb_eException" => "Exception",
- "rb_eStandardError" => "StandardError",
- "rb_eSystemExit" => "SystemExit",
- "rb_eInterrupt" => "Interrupt",
- "rb_eSignal" => "Signal",
- "rb_eFatal" => "Fatal",
- "rb_eArgError" => "ArgError",
- "rb_eEOFError" => "EOFError",
- "rb_eIndexError" => "IndexError",
- "rb_eRangeError" => "RangeError",
- "rb_eIOError" => "IOError",
- "rb_eRuntimeError" => "RuntimeError",
- "rb_eSecurityError" => "SecurityError",
- "rb_eSystemCallError" => "SystemCallError",
- "rb_eTypeError" => "TypeError",
- "rb_eZeroDivError" => "ZeroDivError",
- "rb_eNotImpError" => "NotImpError",
- "rb_eNoMemError" => "NoMemError",
- "rb_eFloatDomainError" => "FloatDomainError",
- "rb_eScriptError" => "ScriptError",
- "rb_eNameError" => "NameError",
- "rb_eSyntaxError" => "SyntaxError",
- "rb_eLoadError" => "LoadError",
-
- "rb_mKernel" => "Kernel",
- "rb_mComparable" => "Comparable",
- "rb_mEnumerable" => "Enumerable",
- "rb_mPrecision" => "Precision",
- "rb_mErrno" => "Errno",
- "rb_mFileTest" => "FileTest",
- "rb_mGC" => "GC",
- "rb_mMath" => "Math",
- "rb_mProcess" => "Process"
-
- }
-
- # See rdoc/c_parse.rb
-
class C_Parser
+ attr_accessor :progress
extend ParserFactory
parse_files_matching(/\.(c|cc|cpp|CC)$/)
@@ -217,8 +219,9 @@ module RDoc
comment.sub!(/\/?\*--.*/m, '')
end
- # remove lines that are commented out that might otherwise get
- # picked up when scanning for classes and methods
+ ##
+ # removes lines that are commented out that might otherwise get picked up
+ # when scanning for classes and methods
def remove_commented_out_lines
@body.gsub!(%r{//.*rb_define_}, '//')
@@ -260,7 +263,6 @@ module RDoc
@classes[var_name] = cm
@known_classes[var_name] = cm.full_name
end
-
############################################################
@@ -425,7 +427,16 @@ module RDoc
end
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.
+ #
+ # /* 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 (\:).
def handle_constants(type, var_name, const_name, definition)
#@stats.num_constants += 1
@@ -442,14 +453,39 @@ module RDoc
comment = find_const_comment(type, const_name)
- con = Constant.new(const_name, definition, mangle_comment(comment))
+ # In the case of rb_define_const, the definition and comment are in
+ # "/* definition: comment */" form. The literal ':' and '\' characters
+ # can be escaped with a backslash.
+ if type.downcase == 'const' then
+ elements = mangle_comment(comment).split(':')
+ if elements.nil? or elements.empty? then
+ con = Constant.new(const_name, definition, mangle_comment(comment))
+ else
+ new_definition = elements[0..-2].join(':')
+ if new_definition.empty? then # Default to literal C definition
+ new_definition = definition
+ else
+ new_definition.gsub!("\:", ":")
+ new_definition.gsub!("\\", '\\')
+ end
+ new_definition.sub!(/\A(\s+)/, '')
+ new_comment = $1.nil? ? elements.last : "#{$1}#{elements.last.lstrip}"
+ con = Constant.new(const_name, new_definition,
+ mangle_comment(new_comment))
+ end
+ else
+ con = Constant.new(const_name, definition, mangle_comment(comment))
+ end
+
class_obj.add_constant(con)
end
- ###########################################################
+ ##
+ # Finds a comment matching +type+ and +const_name+ either above the
+ # comment or in the matching Document- section.
def find_const_comment(type, const_name)
- if @body =~ %r{((?>/\*.*?\*/\s+))
+ if @body =~ %r{((?>^\s*/\*.*?\*/\s+))
rb_define_#{type}\((?:\s*(\w+),)?\s*"#{const_name}"\s*,.*?\)\s*;}xmi
$1
elsif @body =~ %r{Document-(?:const|global|variable):\s#{const_name}\s*?\n((?>.*?\*/))}m
@@ -610,13 +646,15 @@ module RDoc
end
- ##################################################
- #
- # If the comment block contains a section that looks like
+ ##
+ # If the comment block contains a section that looks like:
+ #
# call-seq:
# Array.new
# Array.new(10)
- # use it for the parameters
+ #
+ # use it for the parameters.
+
def find_modifiers(comment, meth_obj)
if comment.sub!(/:nodoc:\s*^\s*\*?\s*$/m, '') or
comment.sub!(/\A\/\*\s*:nodoc:\s*\*\/\Z/, '')
@@ -639,10 +677,11 @@ module RDoc
end
end
- ############################################################
-
- # Look for includes of the form
+ ##
+ # Look for includes of the form:
+ #
# rb_include_module(rb_cArray, rb_mEnumerable);
+
def do_includes
@body.scan(/rb_include_module\s*\(\s*(\w+?),\s*(\w+?)\s*\)/) do |c,m|
if cls = @classes[c]
@@ -652,8 +691,7 @@ module RDoc
end
end
- ############################################################
-
+ ##
# Remove the /*'s and leading asterisks from C comments
def mangle_comment(comment)
@@ -686,7 +724,8 @@ module RDoc
end
end
- # Remove #ifdefs that would otherwise confuse us
+ ##
+ # Removes #ifdefs that would otherwise confuse us
def handle_ifdefs_in(body)
body.gsub(/^#ifdef HAVE_PROTOTYPES.*?#else.*?\n(.*?)#endif.*?\n/m) { $1 }
@@ -695,3 +734,4 @@ module RDoc
end
end
+
diff --git a/test/rdoc/parsers/test_parse_c.rb b/test/rdoc/parsers/test_parse_c.rb
new file mode 100644
index 0000000000..c7815a95c0
--- /dev/null
+++ b/test/rdoc/parsers/test_parse_c.rb
@@ -0,0 +1,148 @@
+require 'pp'
+require 'stringio'
+require 'tempfile'
+require 'test/unit'
+require 'rdoc/parsers/parse_c'
+
+class RDoc::C_Parser
+ attr_accessor :classes
+
+ public :do_classes, :do_constants
+end
+
+class TestRdocC_Parser < Test::Unit::TestCase
+
+ def setup
+ @tempfile = Tempfile.new self.class.name
+ filename = @tempfile.path
+
+ @top_level = RDoc::TopLevel.new filename
+ @fn = filename
+ @options = Options.instance
+ @stats = RDoc::Stats.new
+
+ @progress = StringIO.new
+ end
+
+ def teardown
+ @tempfile.unlink
+ end
+
+ def test_do_constants
+ content = <<-EOF
+#include <ruby.h>
+
+void Init_foo(){
+ VALUE cFoo = rb_define_class("Foo", rb_cObject);
+
+ /* 300: The highest possible score in bowling */
+ rb_define_const(cFoo, "PERFECT", INT2FIX(300));
+
+ /* Huzzah!: What you cheer when you roll a perfect game */
+ rb_define_const(cFoo, "CHEER", rb_str_new2("Huzzah!"));
+
+ /* TEST\:TEST: Checking to see if escaped semicolon works */
+ rb_define_const(cFoo, "TEST", rb_str_new2("TEST:TEST"));
+
+ /* \\: The file separator on MS Windows */
+ rb_define_const(cFoo, "MSEPARATOR", rb_str_new2("\\"));
+
+ /* /: The file separator on Unix */
+ rb_define_const(cFoo, "SEPARATOR", rb_str_new2("/"));
+
+ /* C:\\Program Files\\Stuff: A directory on MS Windows */
+ rb_define_const(cFoo, "STUFF", rb_str_new2("C:\\Program Files\\Stuff"));
+
+ /* Default definition */
+ rb_define_const(cFoo, "NOSEMI", INT2FIX(99));
+
+ rb_define_const(cFoo, "NOCOMMENT", rb_str_new2("No comment"));
+
+ /*
+ * Multiline comment goes here because this comment spans multiple lines.
+ * Multiline comment goes here because this comment spans multiple lines.
+ */
+ rb_define_const(cFoo, "MULTILINE", INT2FIX(1));
+
+ /*
+ * 1: Multiline comment goes here because this comment spans multiple lines.
+ * Multiline comment goes here because this comment spans multiple lines.
+ */
+ rb_define_const(cFoo, "MULTILINE_VALUE", INT2FIX(1));
+
+ /* Multiline comment goes here because this comment spans multiple lines.
+ * Multiline comment goes here because this comment spans multiple lines.
+ */
+ rb_define_const(cFoo, "MULTILINE_NOT_EMPTY", INT2FIX(1));
+
+}
+ EOF
+
+ parser = util_parser content
+
+ parser.do_classes
+ parser.do_constants
+
+ klass = parser.classes['cFoo']
+ assert klass
+
+ constants = klass.constants
+ assert !klass.constants.empty?
+
+ constants = constants.map { |c| [c.name, c.value, c.comment] }
+
+ assert_equal ['PERFECT', '300',
+ "\n The highest possible score in bowling \n "],
+ constants.shift
+ assert_equal ['CHEER', 'Huzzah!',
+ "\n What you cheer when you roll a perfect game \n "],
+ constants.shift
+ assert_equal ['TEST', 'TEST:TEST',
+ "\n Checking to see if escaped semicolon works \n "],
+ constants.shift
+ assert_equal ['MSEPARATOR', '\\',
+ "\n The file separator on MS Windows \n "],
+ constants.shift
+ assert_equal ['SEPARATOR', '/',
+ "\n The file separator on Unix \n "],
+ constants.shift
+ assert_equal ['STUFF', 'C:\\Program Files\\Stuff',
+ "\n A directory on MS Windows \n "],
+ constants.shift
+ assert_equal ['NOSEMI', 'INT2FIX(99)',
+ "\n Default definition \n "],
+ constants.shift
+ assert_equal ['NOCOMMENT', 'rb_str_new2("No comment")', nil],
+ constants.shift
+
+ comment = <<-EOF.chomp
+
+
+ Multiline comment goes here because this comment spans multiple lines.
+ Multiline comment goes here because this comment spans multiple lines.
+
+
+ EOF
+ assert_equal ['MULTILINE', 'INT2FIX(1)', comment], constants.shift
+ assert_equal ['MULTILINE_VALUE', '1', comment], constants.shift
+
+ comment = <<-EOF.chomp
+
+ Multiline comment goes here because this comment spans multiple lines.
+ Multiline comment goes here because this comment spans multiple lines.
+
+
+ EOF
+ assert_equal ['MULTILINE_NOT_EMPTY', 'INT2FIX(1)', comment], constants.shift
+
+ assert constants.empty?, constants.inspect
+ end
+
+ def util_parser(content)
+ parser = RDoc::C_Parser.new @top_level, @fn, content, @options, @stats
+ parser.progress = @progress
+ parser
+ end
+
+end
+