rdoc 2.2.0 → 2.2.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rdoc might be problematic. Click here for more details.

@@ -1,3 +1,35 @@
1
+ === 2.2.1 / 2008-09-24
2
+ This version provides some minor fixes and enhancements to 2.2.0 intended
3
+ to polish RDoc for Ruby 1.9.1.
4
+
5
+ * 3 Minor Enhancements
6
+ * Support for parsing RDoc from SWIG. Ruby patch #10742 by Gonzalo
7
+ Garramuno, #13993 by Steven Jenkins.
8
+ * Simple support for Perl POD documentation. Patch by Hugh Sasse.
9
+ * Changed the default character set of RDoc's output from iso-8859-1 to
10
+ utf-8.
11
+
12
+ * 9 Bug Fixes
13
+ * Explicitly set the html template's text color, so that the generated
14
+ documentation will display correctly on browsers with custom text and
15
+ background color settings (patch by Luther Thompson).
16
+ * Ensure that RDoc correctly will associate an alias and a method, even
17
+ if it encounters the alias first because the alias lives in a different
18
+ file.
19
+ * Fix the parsing of multiline constants (patch by Chris Alfeld and
20
+ Joel VanderWerf)
21
+ * Make --exclude usuable. Ruby patch #11671 by Trans.
22
+ * Detect inline C functions. Ruby Bug #11993 by Florian Frank.
23
+ * Fix an issue in which RDoc might not document a class'
24
+ superclass correctly if the class was defined in multiple files and
25
+ depending on the order in which RDoc processed the files. This should
26
+ ensure that the child class -> parent class relationship is correct in
27
+ ri documentation, allowing ri to lookup inherited methods (i.e., File.read).
28
+ * Stop ri from crashing when it looks for a completely bogus method (i.e.,
29
+ File#reada). Now, ri exits with a helpful error message.
30
+ * Fixed missing display of constant values in ri.
31
+ * Fixed display of constants in ri's html output.
32
+
1
33
  === 2.2.0 / 2008-09-19
2
34
  This version includes some significant enhancements to ri. See RI.txt for
3
35
  documentation about ri.
@@ -47,6 +47,7 @@ lib/rdoc/options.rb
47
47
  lib/rdoc/parser.rb
48
48
  lib/rdoc/parser/c.rb
49
49
  lib/rdoc/parser/f95.rb
50
+ lib/rdoc/parser/perl.rb
50
51
  lib/rdoc/parser/ruby.rb
51
52
  lib/rdoc/parser/simple.rb
52
53
  lib/rdoc/rdoc.rb
@@ -73,6 +74,7 @@ test/test_rdoc_markup_to_html.rb
73
74
  test/test_rdoc_markup_to_html_crossref.rb
74
75
  test/test_rdoc_parser.rb
75
76
  test/test_rdoc_parser_c.rb
77
+ test/test_rdoc_parser_perl.rb
76
78
  test/test_rdoc_parser_ruby.rb
77
79
  test/test_rdoc_ri_attribute_formatter.rb
78
80
  test/test_rdoc_ri_default_display.rb
data/README.txt CHANGED
@@ -46,6 +46,10 @@ The markup engine has lots of little bugs. In particular:
46
46
  * Some output formats (ri, for example) do not correctly handle all of the
47
47
  markup.
48
48
  The markup engine needs a rewrite, which can be tracked here[http://rubyforge.org/tracker/index.php?func=detail&aid=21540&group_id=627&atid=2475].
49
+ ---
50
+ RDoc has some subtle bugs processing classes that are split across multiple
51
+ files (bugs that may or may not manifest depending on the order in which
52
+ the files are encountered). This issue can be tracked here[http://rubyforge.org/tracker/index.php?func=detail&aid=22135&group_id=627&atid=2475].
49
53
  -------
50
54
  If you find a bug, please report it at the RDoc project's
51
55
  tracker[http://rubyforge.org/tracker/?group_id=627] on RubyForge:
@@ -372,7 +372,7 @@ module RDoc
372
372
  ##
373
373
  # RDoc version you are using
374
374
 
375
- VERSION = "2.2.0"
375
+ VERSION = "2.2.1"
376
376
 
377
377
  ##
378
378
  # Name of the dotfile that contains the description of files to be processed
@@ -302,6 +302,7 @@ module RDoc
302
302
  if mod then
303
303
  klass.classes_hash.update(mod.classes_hash)
304
304
  klass.modules_hash.update(mod.modules_hash)
305
+ klass.method_list.concat(mod.method_list)
305
306
  end
306
307
 
307
308
  return klass
@@ -314,25 +315,41 @@ module RDoc
314
315
  def add_method(a_method)
315
316
  a_method.visibility = @visibility
316
317
  add_to(@method_list, a_method)
318
+
319
+ unmatched_alias_list = @unmatched_alias_lists[a_method.name]
320
+ if unmatched_alias_list then
321
+ unmatched_alias_list.each do |unmatched_alias|
322
+ add_alias_impl unmatched_alias, a_method
323
+ @aliases.delete unmatched_alias
324
+ end
325
+
326
+ @unmatched_alias_lists.delete a_method.name
327
+ end
317
328
  end
318
329
 
319
330
  def add_attribute(an_attribute)
320
331
  add_to(@attributes, an_attribute)
321
332
  end
322
333
 
334
+ def add_alias_impl(an_alias, meth)
335
+ new_meth = AnyMethod.new(an_alias.text, an_alias.new_name)
336
+ new_meth.is_alias_for = meth
337
+ new_meth.singleton = meth.singleton
338
+ new_meth.params = meth.params
339
+ new_meth.comment = "Alias for \##{meth.name}"
340
+ meth.add_alias(new_meth)
341
+ add_method(new_meth)
342
+ end
343
+
323
344
  def add_alias(an_alias)
324
345
  meth = find_instance_method_named(an_alias.old_name)
325
346
 
326
347
  if meth then
327
- new_meth = AnyMethod.new(an_alias.text, an_alias.new_name)
328
- new_meth.is_alias_for = meth
329
- new_meth.singleton = meth.singleton
330
- new_meth.params = meth.params
331
- new_meth.comment = "Alias for \##{meth.name}"
332
- meth.add_alias(new_meth)
333
- add_method(new_meth)
348
+ add_alias_impl(an_alias, meth)
334
349
  else
335
350
  add_to(@aliases, an_alias)
351
+ unmatched_alias_list = @unmatched_alias_lists[an_alias.old_name] ||= []
352
+ unmatched_alias_list.push(an_alias)
336
353
  end
337
354
 
338
355
  an_alias
@@ -392,6 +409,10 @@ module RDoc
392
409
  @requires = []
393
410
  @includes = []
394
411
  @constants = []
412
+
413
+ # This Hash maps a method name to a list of unmatched
414
+ # aliases (aliases of a method not yet encountered).
415
+ @unmatched_alias_lists = {}
395
416
  end
396
417
 
397
418
  # and remove classes and modules when we see a :nodoc: all
@@ -609,9 +630,18 @@ module RDoc
609
630
 
610
631
  cls = all[name]
611
632
 
612
- unless cls then
633
+ if !cls then
613
634
  cls = class_type.new name, superclass
614
635
  all[name] = cls unless @done_documenting
636
+ else
637
+ # If the class has been encountered already, check that its
638
+ # superclass has been set (it may not have been, depending on
639
+ # the context in which it was encountered).
640
+ if class_type == NormalClass
641
+ if !cls.superclass then
642
+ cls.superclass = superclass
643
+ end
644
+ end
615
645
  end
616
646
 
617
647
  collection[name] = cls unless @done_documenting
@@ -37,6 +37,7 @@ body {
37
37
  margin-left: 40px;
38
38
  padding: 0;
39
39
  background: white;
40
+ color: black;
40
41
  }
41
42
 
42
43
  h1, h2, h3, h4 {
@@ -38,7 +38,7 @@ Methods
38
38
  <% (method_list["methods"] || []).uniq.each do |method| %>
39
39
  <%= TexinfoTemplate.new(@v.merge({'method' => method, 'list' => method_list}),
40
40
  'method.texinfo.erb').render %><% end %>
41
- <% end # section["method_list"] %>
42
- <% end %>
41
+ <% end %>
42
+ <% end # if section["method_list"] %>
43
43
  <% end # @v['class']["sections"] %>
44
44
  <% end %>
@@ -65,7 +65,7 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
65
65
  # The key thing is that there must be at least
66
66
  # one special character (period, slash, or
67
67
  # underscore).
68
- | \w+[_\/\.][\w\/\.]+
68
+ | [\/\w]+[_\/\.][\w\/\.]+
69
69
 
70
70
  # Things that have markup suppressed
71
71
  | \\[^\s]
@@ -184,7 +184,7 @@ class RDoc::Options
184
184
  @css = nil
185
185
  @webcvs = nil
186
186
 
187
- @charset = 'iso-8859-1'
187
+ @charset = 'utf-8'
188
188
  end
189
189
 
190
190
  ##
@@ -196,6 +196,7 @@ class RDoc::Options
196
196
  opts = OptionParser.new do |opt|
197
197
  opt.program_name = File.basename $0
198
198
  opt.version = RDoc::VERSION
199
+ opt.release = nil
199
200
  opt.summary_indent = ' ' * 4
200
201
  opt.banner = <<-EOF
201
202
  Usage: #{opt.program_name} [options] [names...]
@@ -257,7 +258,7 @@ Usage: #{opt.program_name} [options] [names...]
257
258
  opt.separator nil
258
259
 
259
260
  opt.on("--charset=CHARSET", "-c",
260
- "Specifies the HTML character-set.") do |value|
261
+ "Specifies the output HTML character-set.") do |value|
261
262
  @charset = value
262
263
  end
263
264
 
@@ -283,9 +284,7 @@ Usage: #{opt.program_name} [options] [names...]
283
284
 
284
285
  opt.on("--exclude=PATTERN", "-x", Regexp,
285
286
  "Do not process files or directories",
286
- "matching PATTERN. Files given explicitly",
287
- "on the command line will never be",
288
- "excluded.") do |value|
287
+ "matching PATTERN.") do |value|
289
288
  @exclude << value
290
289
  end
291
290
 
@@ -76,7 +76,7 @@ class RDoc::Parser
76
76
  # Return a parser that can handle a particular extension
77
77
 
78
78
  def self.can_parse(file_name)
79
- parser = RDoc::Parser.parsers.find { |regexp, parser| regexp =~ file_name }.last
79
+ parser = RDoc::Parser.parsers.find { |regexp,| regexp =~ file_name }.last
80
80
 
81
81
  #
82
82
  # The default parser should *NOT* parse binary files.
@@ -120,7 +120,7 @@ class RDoc::Parser::C < RDoc::Parser
120
120
 
121
121
  @stats.add_alias as
122
122
  end
123
- end
123
+ end
124
124
 
125
125
  def do_classes
126
126
  @content.scan(/(\w+)\s* = \s*rb_define_module\s*\(\s*"(\w+)"\s*\)/mx) do
@@ -155,7 +155,7 @@ class RDoc::Parser::C < RDoc::Parser
155
155
  \(
156
156
  \s*(\w+),
157
157
  \s*"(\w+)",
158
- \s*(\w+)\s*
158
+ \s*([\w\*\s\(\)\.\->]+)\s* # for SWIG
159
159
  \s*\)/mx) do |var_name, in_module, class_name, parent|
160
160
  handle_class_module(var_name, "class", class_name, parent, in_module)
161
161
  end
@@ -251,7 +251,7 @@ class RDoc::Parser::C < RDoc::Parser
251
251
  handle_method("method", "rb_mFileTest", meth_name, meth_body, param_count)
252
252
  handle_method("singleton_method", "rb_cFile", meth_name, meth_body, param_count)
253
253
  end
254
- end
254
+ end
255
255
 
256
256
  def find_attr_comment(attr_name)
257
257
  if @content =~ %r{((?>/\*.*?\*/\s+))
@@ -267,9 +267,9 @@ class RDoc::Parser::C < RDoc::Parser
267
267
  ##
268
268
  # Find the C code corresponding to a Ruby method
269
269
 
270
- def find_body(meth_name, meth_obj, body, quiet = false)
270
+ def find_body(class_name, meth_name, meth_obj, body, quiet = false)
271
271
  case body
272
- when %r"((?>/\*.*?\*/\s*))(?:static\s+)?VALUE\s+#{meth_name}
272
+ when %r"((?>/\*.*?\*/\s*)*)(?:(?:static|SWIGINTERN)\s+)?(?:intern\s+)?VALUE\s+#{meth_name}
273
273
  \s*(\([^)]*\))([^;]|$)"xm
274
274
  comment, params = $1, $2
275
275
  body_text = $&
@@ -287,7 +287,7 @@ class RDoc::Parser::C < RDoc::Parser
287
287
  # distinct (for example Kernel.hash and Kernel.object_id share the same
288
288
  # implementation
289
289
 
290
- override_comment = find_override_comment(meth_obj.name)
290
+ override_comment = find_override_comment(class_name, meth_obj.name)
291
291
  comment = override_comment if override_comment
292
292
 
293
293
  find_modifiers(comment, meth_obj) if comment
@@ -298,18 +298,18 @@ class RDoc::Parser::C < RDoc::Parser
298
298
  meth_obj.comment = mangle_comment(comment)
299
299
  when %r{((?>/\*.*?\*/\s*))^\s*\#\s*define\s+#{meth_name}\s+(\w+)}m
300
300
  comment = $1
301
- find_body($2, meth_obj, body, true)
301
+ find_body(class_name, $2, meth_obj, body, true)
302
302
  find_modifiers(comment, meth_obj)
303
303
  meth_obj.comment = mangle_comment(comment) + meth_obj.comment
304
304
  when %r{^\s*\#\s*define\s+#{meth_name}\s+(\w+)}m
305
- unless find_body($1, meth_obj, body, true)
305
+ unless find_body(class_name, $1, meth_obj, body, true)
306
306
  warn "No definition for #{meth_name}" unless @options.quiet
307
307
  return false
308
308
  end
309
309
  else
310
310
 
311
311
  # No body, but might still have an override comment
312
- comment = find_override_comment(meth_obj.name)
312
+ comment = find_override_comment(class_name, meth_obj.name)
313
313
 
314
314
  if comment
315
315
  find_modifiers(comment, meth_obj)
@@ -365,10 +365,10 @@ class RDoc::Parser::C < RDoc::Parser
365
365
  def find_class_comment(class_name, class_meth)
366
366
  comment = nil
367
367
  if @content =~ %r{((?>/\*.*?\*/\s+))
368
- (static\s+)?void\s+Init_#{class_name}\s*(?:_\(\s*)?\(\s*(?:void\s*)\)}xmi
368
+ (static\s+)?void\s+Init_#{class_name}\s*(?:_\(\s*)?\(\s*(?:void\s*)\)}xmi then
369
+ comment = $1
370
+ elsif @content =~ %r{Document-(?:class|module):\s#{class_name}\s*?(?:<\s+[:,\w]+)?\n((?>.*?\*/))}m
369
371
  comment = $1
370
- elsif @content =~ %r{Document-(class|module):\s#{class_name}\s*?\n((?>.*?\*/))}m
371
- comment = $2
372
372
  else
373
373
  if @content =~ /rb_define_(class|module)/m then
374
374
  class_name = class_name.split("::").last
@@ -422,9 +422,11 @@ class RDoc::Parser::C < RDoc::Parser
422
422
  end
423
423
  end
424
424
 
425
- def find_override_comment(meth_name)
425
+ def find_override_comment(class_name, meth_name)
426
426
  name = Regexp.escape(meth_name)
427
- if @content =~ %r{Document-method:\s#{name}\s*?\n((?>.*?\*/))}m
427
+ if @content =~ %r{Document-method:\s+#{class_name}(?:\.|::)#{name}\s*?\n((?>.*?\*/))}m then
428
+ $1
429
+ elsif @content =~ %r{Document-method:\s#{name}\s*?\n((?>.*?\*/))}m then
428
430
  $1
429
431
  end
430
432
  end
@@ -478,6 +480,10 @@ class RDoc::Parser::C < RDoc::Parser
478
480
  end
479
481
 
480
482
  if class_mod == "class" then
483
+ full_name = enclosure.full_name.to_s + "::#{class_name}"
484
+ if @content =~ %r{Document-class:\s+#{full_name}\s*<\s+([:,\w]+)} then
485
+ parent_name = $1
486
+ end
481
487
  cm = enclosure.add_class RDoc::NormalClass, class_name, parent_name
482
488
  @stats.add_class cm
483
489
  else
@@ -588,7 +594,7 @@ class RDoc::Parser::C < RDoc::Parser
588
594
  body = @content
589
595
  end
590
596
 
591
- if find_body(meth_body, meth_obj, body) and meth_obj.document_self then
597
+ if find_body(class_name, meth_body, meth_obj, body) and meth_obj.document_self then
592
598
  class_obj.add_method meth_obj
593
599
  @stats.add_method meth_obj
594
600
  end
@@ -0,0 +1,165 @@
1
+ require 'rdoc/parser'
2
+
3
+ ##
4
+ #
5
+ # This is an attamept to write a basic parser for Perl's
6
+ # POD (Plain old Documentation) format. Ruby code must
7
+ # co-exist with Perl, and some tasks are easier in Perl
8
+ # than Ruby because of existing libraries.
9
+ #
10
+ # One difficult is that Perl POD has no means of identifying
11
+ # the classes (packages) and methods (subs) with which it
12
+ # is associated, it is more like literate programming in so
13
+ # far as it just happens to be in the same place as the code,
14
+ # but need not be.
15
+ #
16
+ # We would like to support all the markup the POD provides
17
+ # so that it will convert happily to HTML. At the moment
18
+ # I don't think I can do that: time constraints.
19
+ #
20
+
21
+ class RDoc::Parser::PerlPOD < RDoc::Parser
22
+
23
+ parse_files_matching(/.p[lm]$/)
24
+
25
+ ##
26
+ # Prepare to parse a perl file
27
+
28
+ def initialize(top_level, file_name, content, options, stats)
29
+ super
30
+
31
+ preprocess = RDoc::Markup::PreProcess.new @file_name, @options.rdoc_include
32
+
33
+ preprocess.handle @content do |directive, param|
34
+ warn "Unrecognized directive '#{directive}' in #{@file_name}"
35
+ end
36
+ end
37
+
38
+ ##
39
+ # Extract the Pod(-like) comments from the code.
40
+ # At its most basic there will ne no need to distinguish
41
+ # between the different types of header, etc.
42
+ #
43
+ # This uses a simple finite state machine, in a very
44
+ # procedural pattern. I could "replace case with polymorphism"
45
+ # but I think it would obscure the intent, scatter the
46
+ # code all over tha place. This machine is necessary
47
+ # because POD requires that directives be preceded by
48
+ # blank lines, so reading line by line is necessary,
49
+ # and preserving state about what is seen is necesary.
50
+
51
+ def scan
52
+
53
+ @top_level.comment ||= ""
54
+ state=:code_blank
55
+ line_number = 0
56
+ line = nil
57
+
58
+ # This started out as a really long nested case statement,
59
+ # which also led to repetitive code. I'd like to avoid that
60
+ # so I'm using a "table" instead.
61
+
62
+ # Firstly we need some procs to do the transition and processing
63
+ # work. Because these are procs they are closures, and they can
64
+ # use variables in the local scope.
65
+ #
66
+ # First, the "nothing to see here" stuff.
67
+ code_noop = lambda do
68
+ if line =~ /^\s+$/
69
+ state = :code_blank
70
+ end
71
+ end
72
+
73
+ pod_noop = lambda do
74
+ if line =~ /^\s+$/
75
+ state = :pod_blank
76
+ end
77
+ @top_level.comment += filter(line)
78
+ end
79
+
80
+ begin_noop = lambda do
81
+ if line =~ /^\s+$/
82
+ state = :begin_blank
83
+ end
84
+ @top_level.comment += filter(line)
85
+ end
86
+
87
+ # Now for the blocks that process code and comments...
88
+
89
+ transit_to_pod = lambda do
90
+ case line
91
+ when /^=(?:pod|head\d+)/
92
+ state = :pod_no_blank
93
+ @top_level.comment += filter(line)
94
+ when /^=over/
95
+ state = :over_no_blank
96
+ @top_level.comment += filter(line)
97
+ when /^=(?:begin|for)/
98
+ state = :begin_no_blank
99
+ end
100
+ end
101
+
102
+ process_pod = lambda do
103
+ case line
104
+ when /^\s*$/
105
+ state = :pod_blank
106
+ @top_level.comment += filter(line)
107
+ when /^=cut/
108
+ state = :code_no_blank
109
+ when /^=end/
110
+ $stderr.puts "'=end' unexpected at #{line_number} in #{@file_name}"
111
+ else
112
+ @top_level.comment += filter(line)
113
+ end
114
+ end
115
+
116
+
117
+ process_begin = lambda do
118
+ case line
119
+ when /^\s*$/
120
+ state = :begin_blank
121
+ @top_level.comment += filter(line)
122
+ when /^=end/
123
+ state = :code_no_blank
124
+ when /^=cut/
125
+ $stderr.puts "'=cut' unexpected at #{line_number} in #{@file_name}"
126
+ else
127
+ @top_level.comment += filter(line)
128
+ end
129
+
130
+ end
131
+
132
+
133
+ transitions = { :code_no_blank => code_noop,
134
+ :code_blank => transit_to_pod,
135
+ :pod_no_blank => pod_noop,
136
+ :pod_blank => process_pod,
137
+ :begin_no_blank => begin_noop,
138
+ :begin_blank => process_begin}
139
+ @content.each_line do |l|
140
+ line = l
141
+ line_number += 1
142
+ transitions[state].call
143
+ end # each line
144
+
145
+ @top_level
146
+ end
147
+
148
+ # Filter the perl markup that does the same as the rdoc
149
+ # filtering. Only basic for now. Will probably need a
150
+ # proper parser to cope with C<<...>> etc
151
+ def filter(comment)
152
+ return '' if comment =~ /^=pod\s*$/
153
+ comment.gsub!(/^=pod/, '==')
154
+ comment.gsub!(/^=head(\d+)/) do
155
+ "=" * $1.to_i
156
+ end
157
+ comment.gsub!(/=item/, '');
158
+ comment.gsub!(/C<(.*?)>/, '<tt>\1</tt>');
159
+ comment.gsub!(/I<(.*?)>/, '<i>\1</i>');
160
+ comment.gsub!(/B<(.*?)>/, '<b>\1</b>');
161
+ comment
162
+ end
163
+
164
+ end
165
+
@@ -1945,9 +1945,9 @@ class RDoc::Parser::Ruby < RDoc::Parser
1945
1945
  case tk
1946
1946
  when TkSEMICOLON
1947
1947
  break
1948
- when TkLPAREN, TkfLPAREN
1948
+ when TkLPAREN, TkfLPAREN, TkLBRACE, TkLBRACK, TkDO
1949
1949
  nest += 1
1950
- when TkRPAREN
1950
+ when TkRPAREN, TkRBRACE, TkRBRACK, TkEND
1951
1951
  nest -= 1
1952
1952
  when TkCOMMENT
1953
1953
  if nest <= 0 && @scanner.lex_state == EXPR_END
@@ -1955,7 +1955,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
1955
1955
  break
1956
1956
  end
1957
1957
  when TkNL
1958
- if (@scanner.lex_state == EXPR_END and nest <= 0) || !@scanner.continue
1958
+ if (nest <= 0) && ((@scanner.lex_state == EXPR_END) || (!@scanner.continue))
1959
1959
  unget_tk(tk)
1960
1960
  break
1961
1961
  end
@@ -7,6 +7,7 @@ require 'rdoc/parser/simple'
7
7
  require 'rdoc/parser/ruby'
8
8
  require 'rdoc/parser/c'
9
9
  require 'rdoc/parser/f95'
10
+ require 'rdoc/parser/perl'
10
11
 
11
12
  require 'rdoc/stats'
12
13
  require 'rdoc/options'
@@ -189,11 +190,11 @@ module RDoc
189
190
 
190
191
  def parse_files(options)
191
192
  @stats = Stats.new options.verbosity
192
-
193
+
193
194
  files = options.files
194
195
  files = ["."] if files.empty?
195
196
 
196
- file_list = normalized_file_list(options, files, true)
197
+ file_list = normalized_file_list(options, files, true, options.exclude)
197
198
 
198
199
  return [] if file_list.empty?
199
200
 
@@ -86,21 +86,19 @@ class RDoc::RI::DefaultDisplay
86
86
  constants = klass.constants.sort_by { |constant| constant.name }
87
87
 
88
88
  constants.each do |constant|
89
+ @formatter.wrap "#{constant.name} = #{constant.value}"
89
90
  if constant.comment then
90
- @formatter.wrap "#{constant.name}:"
91
-
92
91
  @formatter.indent do
93
92
  @formatter.display_flow constant.comment
94
93
  end
95
94
  else
96
- @formatter.wrap constant.name
95
+ @formatter.break_to_newline
97
96
  end
98
97
  end
99
98
  end
100
99
 
101
100
  unless klass.attributes.empty? then
102
101
  @formatter.blankline
103
-
104
102
  @formatter.display_heading 'Attributes:', 2, ''
105
103
 
106
104
  attributes = klass.attributes.sort_by { |attribute| attribute.name }
@@ -113,6 +111,7 @@ class RDoc::RI::DefaultDisplay
113
111
  end
114
112
  else
115
113
  @formatter.wrap "#{attribute.name} (#{attribute.rw})"
114
+ @formatter.break_to_newline
116
115
  end
117
116
  end
118
117
  end
@@ -77,14 +77,12 @@ class RDoc::RI::Driver
77
77
 
78
78
  attr_accessor :homepath # :nodoc:
79
79
 
80
- def self.process_args(argv)
80
+ def self.default_options
81
81
  options = {}
82
82
  options[:use_stdout] = !$stdout.tty?
83
83
  options[:width] = 72
84
84
  options[:formatter] = RDoc::RI::Formatter.for 'plain'
85
85
  options[:interactive] = false
86
- options[:list_classes] = false
87
- options[:list_names] = false
88
86
  options[:use_cache] = true
89
87
 
90
88
  # By default all standard paths are used.
@@ -94,9 +92,16 @@ class RDoc::RI::Driver
94
92
  options[:use_gems] = true
95
93
  options[:extra_doc_dirs] = []
96
94
 
95
+ return options
96
+ end
97
+
98
+ def self.process_args(argv)
99
+ options = default_options
100
+
97
101
  opts = OptionParser.new do |opt|
98
102
  opt.program_name = File.basename $0
99
103
  opt.version = RDoc::VERSION
104
+ opt.release = nil
100
105
  opt.summary_indent = ' ' * 4
101
106
 
102
107
  directories = [
@@ -151,14 +156,6 @@ Options may also be set in the 'RI' environment variable.
151
156
  opt.separator "Options:"
152
157
  opt.separator nil
153
158
 
154
- opt.on("--classes", "-c",
155
- "Display the names of classes and modules we",
156
- "know about.") do |value|
157
- options[:list_classes] = value
158
- end
159
-
160
- opt.separator nil
161
-
162
159
  opt.on("--fmt=FORMAT", "--format=FORMAT", "-f",
163
160
  RDoc::RI::Formatter::FORMATTERS.keys,
164
161
  "Format to use when displaying output:",
@@ -251,14 +248,6 @@ Options may also be set in the 'RI' environment variable.
251
248
 
252
249
  opt.separator nil
253
250
 
254
- opt.on("--list-names", "-l",
255
- "List all the names known to RDoc, one per",
256
- "line.") do
257
- options[:list_names] = true
258
- end
259
-
260
- opt.separator nil
261
-
262
251
  opt.on("--no-pager", "-T",
263
252
  "Send output directly to stdout,",
264
253
  "rather than to a pager.") do
@@ -311,9 +300,10 @@ Options may also be set in the 'RI' environment variable.
311
300
  ri.run
312
301
  end
313
302
 
314
- def initialize(options={})
315
- @names = options[:names]
303
+ def initialize(initial_options={})
304
+ options = self.class.default_options.update(initial_options)
316
305
 
306
+ @names = options[:names]
317
307
  @class_cache_name = 'classes'
318
308
 
319
309
  @doc_dirs = RDoc::RI::Paths.path(options[:use_system],
@@ -380,7 +370,7 @@ Options may also be set in the 'RI' environment variable.
380
370
  else
381
371
  @class_cache = create_class_cache
382
372
  end
383
-
373
+
384
374
  @class_cache
385
375
  end
386
376
 
@@ -513,7 +503,7 @@ Options may also be set in the 'RI' environment variable.
513
503
  cache[name] = method
514
504
  end
515
505
  end
516
-
506
+
517
507
  write_cache cache, path
518
508
  end
519
509
 
@@ -521,6 +511,15 @@ Options may also be set in the 'RI' environment variable.
521
511
  # Finds the next ancestor of +orig_klass+ after +klass+.
522
512
 
523
513
  def lookup_ancestor(klass, orig_klass)
514
+ # This is a bit hacky, but ri will go into an infinite
515
+ # loop otherwise, since Object has an Object ancestor
516
+ # for some reason. Depending on the documentation state, I've seen
517
+ # Kernel as an ancestor of Object and not as an ancestor of Object.
518
+ if ((orig_klass == "Object") &&
519
+ ((klass == "Kernel") || (klass == "Object")))
520
+ return nil
521
+ end
522
+
524
523
  cache = class_cache[orig_klass]
525
524
 
526
525
  return nil unless cache
@@ -528,10 +527,13 @@ Options may also be set in the 'RI' environment variable.
528
527
  ancestors = [orig_klass]
529
528
  ancestors.push(*cache.includes.map { |inc| inc['name'] })
530
529
  ancestors << cache.superclass
530
+
531
+ ancestor_index = ancestors.index(klass)
531
532
 
532
- ancestor = ancestors[ancestors.index(klass) + 1]
533
-
534
- return ancestor if ancestor
533
+ if ancestor_index
534
+ ancestor = ancestors[ancestors.index(klass) + 1]
535
+ return ancestor if ancestor
536
+ end
535
537
 
536
538
  lookup_ancestor klass, cache.superclass
537
539
  end
@@ -551,7 +553,7 @@ Options may also be set in the 'RI' environment variable.
551
553
  def map_dirs(file_name)
552
554
  @doc_dirs.map { |dir| yield File.join(dir, file_name) }.flatten.compact
553
555
  end
554
-
556
+
555
557
  ##
556
558
  # Extract the class and method name parts from +name+ like Foo::Bar#baz
557
559
 
@@ -598,29 +600,29 @@ Options may also be set in the 'RI' environment variable.
598
600
  end
599
601
  elsif name =~ /::|\#|\./ then
600
602
  klass, = parse_name name
601
-
603
+
602
604
  orig_klass = klass
603
605
  orig_name = name
604
-
606
+
605
607
  loop do
606
608
  method = lookup_method name, klass
607
-
609
+
608
610
  break method if method
609
-
611
+
610
612
  ancestor = lookup_ancestor klass, orig_klass
611
-
613
+
612
614
  break unless ancestor
613
-
615
+
614
616
  name = name.sub klass, ancestor
615
617
  klass = ancestor
616
618
  end
617
-
619
+
618
620
  raise NotFoundError, orig_name unless method
619
-
621
+
620
622
  display_method method
621
623
  else
622
624
  methods = select_methods(/#{name}/)
623
-
625
+
624
626
  if methods.size == 0
625
627
  raise NotFoundError, name
626
628
  elsif methods.size == 1
@@ -660,7 +662,7 @@ Options may also be set in the 'RI' environment variable.
660
662
  Marshal.dump cache, cache_file
661
663
  end
662
664
  end
663
-
665
+
664
666
  cache
665
667
  end
666
668
 
@@ -127,7 +127,8 @@ class TestRDocMarkupToHtmlCrossref < Test::Unit::TestCase
127
127
  # file_name (String) for String reference.
128
128
  #
129
129
  def verify_file_crossref(xref, reference, file_name)
130
- result = "<a href=\"../files/#{file_name.gsub(/\./, '_')}.html\">#{reference}</a>"
130
+ generated_document_path = Pathname.new("../files/#{file_name.gsub(/\./, '_')}.html").cleanpath.to_s
131
+ result = "<a href=\"#{generated_document_path}\">#{reference}</a>"
131
132
 
132
133
  verify_convert xref, reference, result
133
134
  end
@@ -244,9 +244,36 @@ Init_Foo(void) {
244
244
  assert_equal " \n a comment for class Foo on Init\n \n", klass.comment
245
245
  end
246
246
 
247
+ def test_define_method
248
+ content = <<-EOF
249
+ /*Method Comment! */
250
+ static VALUE
251
+ rb_io_s_read(argc, argv, io)
252
+ int argc;
253
+ VALUE *argv;
254
+ VALUE io;
255
+ {
256
+ }
257
+
258
+ void
259
+ Init_IO(void) {
260
+ /*
261
+ * a comment for class Foo on rb_define_class
262
+ */
263
+ VALUE rb_cIO = rb_define_class("IO", rb_cObject);
264
+ rb_define_singleton_method(rb_cIO, "read", rb_io_s_read, -1);
265
+ }
266
+ EOF
267
+
268
+ klass = util_get_class content, 'rb_cIO'
269
+ read_method = klass.method_list.first
270
+ assert_equal "read", read_method.name
271
+ assert_equal " Method Comment! \n", read_method.comment
272
+ end
273
+
247
274
  def util_get_class(content, name)
248
275
  parser = util_parser content
249
- parser.do_classes
276
+ parser.scan
250
277
  parser.classes[name]
251
278
  end
252
279
 
@@ -0,0 +1,72 @@
1
+ require 'stringio'
2
+ require 'tempfile'
3
+ require 'test/unit'
4
+ require 'rdoc/options'
5
+ require 'rdoc/parser/perl'
6
+
7
+ class TestRdocParserPerlPOD < Test::Unit::TestCase
8
+
9
+ def setup
10
+ @tempfile = Tempfile.new self.class.name
11
+ filename = @tempfile.path
12
+
13
+ @top_level = RDoc::TopLevel.new filename
14
+ @fn = filename
15
+ @options = RDoc::Options.new
16
+ @stats = RDoc::Stats.new 0
17
+ end
18
+
19
+ def teardown
20
+ @tempfile.close
21
+ end
22
+
23
+ def test_uncommented_perl
24
+ content = <<-EOF
25
+ while (<>) {
26
+ tr/a-z/A-Z;
27
+ print
28
+ }
29
+ EOF
30
+
31
+ comment = util_get_comment content
32
+ assert_equal "", comment
33
+ end
34
+
35
+ def test_perl_without_pod
36
+ content = <<-EOF
37
+ #!/usr/local/bin/perl
38
+ #
39
+ #This is a pointless perl program because it does -p.
40
+ #
41
+ while(<>) {print;}:
42
+ EOF
43
+
44
+ comment = util_get_comment content
45
+ assert_equal "", comment
46
+ end
47
+
48
+ def test_simple_pod_no_structure
49
+ content = <<-EOF
50
+ =begin pod
51
+
52
+ This just contains plain old documentation
53
+
54
+ =end
55
+ EOF
56
+ comment = util_get_comment content
57
+ assert_equal "\nThis just contains plain old documentation\n\n", comment
58
+ end
59
+
60
+ # Get the comment of the @top_level when it has processed the input.
61
+ def util_get_comment(content)
62
+ parser = util_parser content
63
+ parser.scan.comment
64
+ end
65
+
66
+ # create a new parser with the supplied content.
67
+ def util_parser(content)
68
+ RDoc::Parser::PerlPOD.new @top_level, @fn, content, @options, @stats
69
+ end
70
+
71
+ end
72
+
@@ -12,6 +12,10 @@ class TestRDocParserRuby < Test::Unit::TestCase
12
12
  @tempfile = Tempfile.new self.class.name
13
13
  @filename = @tempfile.path
14
14
 
15
+ # Some tests need two paths.
16
+ @tempfile2 = Tempfile.new self.class.name
17
+ @filename2 = @tempfile2.path
18
+
15
19
  util_toplevel
16
20
  @options = RDoc::Options.new
17
21
  @options.quiet = true
@@ -20,6 +24,7 @@ class TestRDocParserRuby < Test::Unit::TestCase
20
24
 
21
25
  def teardown
22
26
  @tempfile.unlink
27
+ @tempfile2.unlink
23
28
  end
24
29
 
25
30
  def test_look_for_directives_in_commented
@@ -204,6 +209,34 @@ EOF
204
209
  assert_equal 'Foo::Baz', baz.full_name
205
210
  end
206
211
 
212
+ def test_parse_class_definition_encountered_after_class_reference
213
+ #
214
+ # The code below is not strictly legal Ruby (Foo must have been defined
215
+ # before Foo.bar is encountered), but RDoc might encounter Foo.bar before
216
+ # Foo if they live in different files.
217
+ #
218
+ code = <<-EOF
219
+ def Foo.bar
220
+ end
221
+
222
+ class Foo < IO
223
+ end
224
+ EOF
225
+
226
+ util_parser code
227
+
228
+ @parser.scan()
229
+
230
+ assert(@top_level.modules.empty?)
231
+
232
+ foo = @top_level.classes.first
233
+ assert_equal 'Foo', foo.full_name
234
+ assert_equal 'IO', foo.superclass
235
+
236
+ bar = foo.method_list.first
237
+ assert_equal 'bar', bar.name
238
+ end
239
+
207
240
  def test_parse_module_relative_to_top_level_namespace
208
241
  comment = <<-EOF
209
242
  #
@@ -487,9 +520,107 @@ end
487
520
 
488
521
  @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL, nil, ''
489
522
 
523
+ foo = @top_level.classes.first.method_list[0]
524
+ assert_equal 'foo', foo.name
525
+
490
526
  foo2 = @top_level.classes.first.method_list.last
491
527
  assert_equal 'foo2', foo2.name
492
528
  assert_equal 'foo', foo2.is_alias_for.name
529
+ assert @top_level.classes.first.aliases.empty?
530
+ end
531
+
532
+ def test_parse_statements_identifier_alias_method_before_original_method
533
+ # This is not strictly legal Ruby code, but it simulates finding an alias
534
+ # for a method before finding the original method, which might happen
535
+ # to rdoc if the alias is in a different file than the original method
536
+ # and rdoc processes the alias' file first.
537
+ content = <<-EOF
538
+ class Foo
539
+ alias_method :foo2, :foo
540
+
541
+ alias_method :foo3, :foo
542
+
543
+ def foo()
544
+ end
545
+
546
+ alias_method :foo4, :foo
547
+
548
+ alias_method :foo5, :unknown
549
+ end
550
+ EOF
551
+
552
+ util_parser content
553
+
554
+ @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL, nil, ''
555
+
556
+ foo = @top_level.classes.first.method_list[0]
557
+ assert_equal 'foo', foo.name
558
+
559
+ foo2 = @top_level.classes.first.method_list[1]
560
+ assert_equal 'foo2', foo2.name
561
+ assert_equal 'foo', foo2.is_alias_for.name
562
+
563
+ foo3 = @top_level.classes.first.method_list[2]
564
+ assert_equal 'foo3', foo3.name
565
+ assert_equal 'foo', foo3.is_alias_for.name
566
+
567
+ foo4 = @top_level.classes.first.method_list.last
568
+ assert_equal 'foo4', foo4.name
569
+ assert_equal 'foo', foo4.is_alias_for.name
570
+
571
+ assert_equal 'unknown', @top_level.classes.first.aliases[0].old_name
572
+ end
573
+
574
+ def test_parse_statements_identifier_constant
575
+ content = <<-EOF
576
+ class Foo
577
+ FIRST_CONSTANT = 5
578
+
579
+ SECOND_CONSTANT = [
580
+ 1,
581
+ 2,
582
+ 3
583
+ ]
584
+
585
+ THIRD_CONSTANT = {
586
+ :foo => 'bar',
587
+ :x => 'y'
588
+ }
589
+
590
+ FOURTH_CONSTANT = SECOND_CONSTANT.map do |element|
591
+ element + 1
592
+ element + 2
593
+ end
594
+
595
+ FIFTH_CONSTANT = SECOND_CONSTANT.map { |element| element + 1 }
596
+ end
597
+ EOF
598
+
599
+ util_parser content
600
+
601
+ @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL, nil, ''
602
+
603
+ constants = @top_level.classes.first.constants
604
+
605
+ constant = constants[0]
606
+ assert_equal 'FIRST_CONSTANT', constant.name
607
+ assert_equal '5', constant.value
608
+
609
+ constant = constants[1]
610
+ assert_equal 'SECOND_CONSTANT', constant.name
611
+ assert_equal '[ 1, 2, 3 ]', constant.value
612
+
613
+ constant = constants[2]
614
+ assert_equal 'THIRD_CONSTANT', constant.name
615
+ assert_equal "{ :foo => 'bar', :x => 'y' }", constant.value
616
+
617
+ constant = constants[3]
618
+ assert_equal 'FOURTH_CONSTANT', constant.name
619
+ assert_equal 'SECOND_CONSTANT.map do |element| element + 1 element + 2 end', constant.value
620
+
621
+ constant = constants.last
622
+ assert_equal 'FIFTH_CONSTANT', constant.name
623
+ assert_equal 'SECOND_CONSTANT.map { |element| element + 1 }', constant.value
493
624
  end
494
625
 
495
626
  def test_parse_statements_identifier_attr
@@ -601,9 +732,17 @@ end
601
732
  @stats
602
733
  end
603
734
 
735
+ def util_two_parsers(first_file_content, second_file_content)
736
+ util_parser first_file_content
737
+
738
+ @parser2 = RDoc::Parser::Ruby.new @top_level2, @filename,
739
+ second_file_content, @options, @stats
740
+ end
741
+
604
742
  def util_toplevel
605
743
  RDoc::TopLevel.reset
606
744
  @top_level = RDoc::TopLevel.new @filename
745
+ @top_level2 = RDoc::TopLevel.new @filename2
607
746
  end
608
747
 
609
748
  end
@@ -42,9 +42,9 @@ class TestRDocRiDefaultDisplay < Test::Unit::TestCase
42
42
  ],
43
43
  'comment' => [RDoc::Markup::Flow::P.new('SomeClass comment')],
44
44
  'constants' => [
45
- { 'name' => 'CONSTANT', 'value' => '"value"',
45
+ { 'name' => 'CONSTANT', 'value' => '"value1"',
46
46
  'comment' => [RDoc::Markup::Flow::P.new('CONSTANT value')] },
47
- { 'name' => 'CONSTANT_NOCOMMENT', 'value' => '"value"',
47
+ { 'name' => 'CONSTANT_NOCOMMENT', 'value' => '"value2"',
48
48
  'comment' => nil },
49
49
  ],
50
50
  'display_name' => 'Class',
@@ -70,10 +70,10 @@ class TestRDocRiDefaultDisplay < Test::Unit::TestCase
70
70
  Constants:
71
71
  ----------
72
72
 
73
- CONSTANT:
73
+ CONSTANT = "value1"
74
74
  CONSTANT value
75
75
 
76
- CONSTANT_NOCOMMENT
76
+ CONSTANT_NOCOMMENT = "value2"
77
77
 
78
78
 
79
79
  Attributes:
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rdoc
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 2.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Hodel
@@ -12,7 +12,7 @@ autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
14
 
15
- date: 2008-09-19 00:00:00 -04:00
15
+ date: 2008-09-24 00:00:00 -04:00
16
16
  default_executable:
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
@@ -91,6 +91,7 @@ files:
91
91
  - lib/rdoc/parser.rb
92
92
  - lib/rdoc/parser/c.rb
93
93
  - lib/rdoc/parser/f95.rb
94
+ - lib/rdoc/parser/perl.rb
94
95
  - lib/rdoc/parser/ruby.rb
95
96
  - lib/rdoc/parser/simple.rb
96
97
  - lib/rdoc/rdoc.rb
@@ -117,6 +118,7 @@ files:
117
118
  - test/test_rdoc_markup_to_html_crossref.rb
118
119
  - test/test_rdoc_parser.rb
119
120
  - test/test_rdoc_parser_c.rb
121
+ - test/test_rdoc_parser_perl.rb
120
122
  - test/test_rdoc_parser_ruby.rb
121
123
  - test/test_rdoc_ri_attribute_formatter.rb
122
124
  - test/test_rdoc_ri_default_display.rb
@@ -157,6 +159,7 @@ test_files:
157
159
  - test/test_rdoc_markup_to_html_crossref.rb
158
160
  - test/test_rdoc_info_sections.rb
159
161
  - test/test_rdoc_ri_formatter.rb
162
+ - test/test_rdoc_parser_perl.rb
160
163
  - test/test_rdoc_ri_driver.rb
161
164
  - test/test_attribute_manager.rb
162
165
  - test/test_rdoc_parser_ruby.rb