diff options
Diffstat (limited to 'lib/rdoc/parser')
-rw-r--r-- | lib/rdoc/parser/c.rb | 414 | ||||
-rw-r--r-- | lib/rdoc/parser/perl.rb | 165 | ||||
-rw-r--r-- | lib/rdoc/parser/ruby.rb | 333 | ||||
-rw-r--r-- | lib/rdoc/parser/ruby_tools.rb | 5 | ||||
-rw-r--r-- | lib/rdoc/parser/simple.rb | 13 |
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 |