rdoc 2.0.0 → 2.1.0

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.

Files changed (52) hide show
  1. data.tar.gz.sig +1 -0
  2. data/History.txt +30 -0
  3. data/Manifest.txt +18 -6
  4. data/Rakefile +52 -0
  5. data/lib/rdoc.rb +69 -69
  6. data/lib/rdoc/code_objects.rb +331 -112
  7. data/lib/rdoc/generator.rb +172 -144
  8. data/lib/rdoc/generator/html.rb +45 -18
  9. data/lib/rdoc/generator/html/frameless.rb +795 -0
  10. data/lib/rdoc/generator/html/hefss.rb +11 -11
  11. data/lib/rdoc/generator/html/html.rb +81 -87
  12. data/lib/rdoc/generator/html/kilmer.rb +10 -10
  13. data/lib/rdoc/generator/html/one_page_html.rb +9 -9
  14. data/lib/rdoc/generator/ri.rb +5 -8
  15. data/lib/rdoc/generator/texinfo.rb +84 -0
  16. data/lib/rdoc/generator/texinfo/class.texinfo.erb +44 -0
  17. data/lib/rdoc/generator/texinfo/file.texinfo.erb +6 -0
  18. data/lib/rdoc/generator/texinfo/method.texinfo.erb +6 -0
  19. data/lib/rdoc/generator/texinfo/texinfo.erb +28 -0
  20. data/lib/rdoc/known_classes.rb +69 -0
  21. data/lib/rdoc/markup.rb +3 -3
  22. data/lib/rdoc/markup/attribute_manager.rb +0 -9
  23. data/lib/rdoc/markup/fragments.rb +1 -1
  24. data/lib/rdoc/markup/preprocess.rb +10 -6
  25. data/lib/rdoc/markup/to_html.rb +55 -8
  26. data/lib/rdoc/markup/to_html_crossref.rb +21 -5
  27. data/lib/rdoc/markup/to_texinfo.rb +69 -0
  28. data/lib/rdoc/options.rb +37 -14
  29. data/lib/rdoc/parser.rb +109 -0
  30. data/lib/rdoc/parser/c.rb +656 -0
  31. data/lib/rdoc/parser/f95.rb +1835 -0
  32. data/lib/rdoc/{parsers/parse_rb.rb → parser/ruby.rb} +1436 -1191
  33. data/lib/rdoc/parser/simple.rb +38 -0
  34. data/lib/rdoc/rdoc.rb +48 -32
  35. data/lib/rdoc/ri.rb +5 -1
  36. data/lib/rdoc/ri/descriptions.rb +8 -5
  37. data/lib/rdoc/ri/driver.rb +148 -49
  38. data/lib/rdoc/stats.rb +94 -4
  39. data/test/test_rdoc_info_formatting.rb +175 -0
  40. data/test/test_rdoc_info_sections.rb +136 -0
  41. data/test/test_rdoc_markup_to_html.rb +30 -0
  42. data/test/test_rdoc_markup_to_html_crossref.rb +18 -0
  43. data/test/{test_rdoc_c_parser.rb → test_rdoc_parser_c.rb} +8 -11
  44. data/test/test_rdoc_parser_ruby.rb +539 -0
  45. data/test/test_rdoc_ri_default_display.rb +17 -16
  46. data/test/test_rdoc_ri_driver.rb +92 -0
  47. metadata +54 -12
  48. metadata.gz.sig +0 -0
  49. data/lib/rdoc/parsers/parse_c.rb +0 -775
  50. data/lib/rdoc/parsers/parse_f95.rb +0 -1841
  51. data/lib/rdoc/parsers/parse_simple.rb +0 -40
  52. data/lib/rdoc/parsers/parserfactory.rb +0 -99
@@ -0,0 +1,38 @@
1
+ require 'rdoc/parser'
2
+
3
+ ##
4
+ # Parse a non-source file. We basically take the whole thing as one big
5
+ # comment. If the first character in the file is '#', we strip leading pound
6
+ # signs.
7
+
8
+ class RDoc::Parser::Simple < RDoc::Parser
9
+
10
+ parse_files_matching(//)
11
+
12
+ ##
13
+ # Prepare to parse a plain file
14
+
15
+ def initialize(top_level, file_name, content, options, stats)
16
+ super
17
+
18
+ preprocess = RDoc::Markup::PreProcess.new @file_name, @options.rdoc_include
19
+
20
+ preprocess.handle @content do |directive, param|
21
+ warn "Unrecognized directive '#{directive}' in #{@file_name}"
22
+ end
23
+ end
24
+
25
+ ##
26
+ # Extract the file contents and attach them to the toplevel as a comment
27
+
28
+ def scan
29
+ @top_level.comment = remove_private_comments(@content)
30
+ @top_level
31
+ end
32
+
33
+ def remove_private_comments(comment)
34
+ comment.gsub(/^--[^-].*?^\+\+/m, '').sub(/^--.*/m, '')
35
+ end
36
+
37
+ end
38
+
@@ -1,9 +1,12 @@
1
1
  require 'rdoc'
2
2
 
3
- require 'rdoc/parsers/parse_rb.rb'
4
- require 'rdoc/parsers/parse_c.rb'
5
- require 'rdoc/parsers/parse_f95.rb'
6
- require 'rdoc/parsers/parse_simple.rb'
3
+ require 'rdoc/parser'
4
+
5
+ # Simple must come first
6
+ require 'rdoc/parser/simple'
7
+ require 'rdoc/parser/ruby'
8
+ require 'rdoc/parser/c'
9
+ require 'rdoc/parser/f95'
7
10
 
8
11
  require 'rdoc/stats'
9
12
  require 'rdoc/options'
@@ -17,21 +20,24 @@ require 'time'
17
20
  module RDoc
18
21
 
19
22
  ##
20
- # Encapsulate the production of rdoc documentation. Basically
21
- # you can use this as you would invoke rdoc from the command
22
- # line:
23
+ # Encapsulate the production of rdoc documentation. Basically you can use
24
+ # this as you would invoke rdoc from the command line:
23
25
  #
24
- # rdoc = RDoc::RDoc.new
25
- # rdoc.document(args)
26
+ # rdoc = RDoc::RDoc.new
27
+ # rdoc.document(args)
26
28
  #
27
- # where _args_ is an array of strings, each corresponding to
28
- # an argument you'd give rdoc on the command line. See rdoc/rdoc.rb
29
- # for details.
29
+ # Where +args+ is an array of strings, each corresponding to an argument
30
+ # you'd give rdoc on the command line. See rdoc/rdoc.rb for details.
30
31
 
31
32
  class RDoc
32
33
 
33
34
  Generator = Struct.new(:file_name, :class_name, :key)
34
35
 
36
+ ##
37
+ # Accessor for statistics. Available after each call to parse_files
38
+
39
+ attr_reader :stats
40
+
35
41
  ##
36
42
  # This is the list of output generator that we support
37
43
 
@@ -54,7 +60,7 @@ module RDoc
54
60
  end
55
61
 
56
62
  def initialize
57
- @stats = Stats.new
63
+ @stats = nil
58
64
  end
59
65
 
60
66
  ##
@@ -134,7 +140,7 @@ module RDoc
134
140
  # subdirectories.
135
141
  #
136
142
  # The effect of this is that if you want a file with a non-standard
137
- # extension parsed, you must name it explicity.
143
+ # extension parsed, you must name it explicitly.
138
144
 
139
145
  def normalized_file_list(options, relative_files, force_doc = false,
140
146
  exclude_pattern = nil)
@@ -146,7 +152,10 @@ module RDoc
146
152
  case type = stat.ftype
147
153
  when "file"
148
154
  next if @last_created and stat.mtime < @last_created
149
- file_list << rel_file_name.sub(/^\.\//, '') if force_doc || ParserFactory.can_parse(rel_file_name)
155
+
156
+ if force_doc or ::RDoc::Parser.can_parse(rel_file_name) then
157
+ file_list << rel_file_name.sub(/^\.\//, '')
158
+ end
150
159
  when "directory"
151
160
  next if rel_file_name == "CVS" || rel_file_name == ".svn"
152
161
  dot_doc = File.join(rel_file_name, DOT_DOC_FILENAME)
@@ -179,6 +188,8 @@ module RDoc
179
188
  # Parse each file on the command line, recursively entering directories.
180
189
 
181
190
  def parse_files(options)
191
+ @stats = Stats.new options.verbosity
192
+
182
193
  files = options.files
183
194
  files = ["."] if files.empty?
184
195
 
@@ -187,27 +198,30 @@ module RDoc
187
198
  return [] if file_list.empty?
188
199
 
189
200
  file_info = []
190
- width = file_list.map { |name| name.length }.max + 1
191
201
 
192
- file_list.each do |fn|
193
- $stderr.printf("\n%*s: ", width, fn) unless options.quiet
202
+ file_list.each do |filename|
203
+ @stats.add_file filename
194
204
 
195
205
  content = if RUBY_VERSION >= '1.9' then
196
- File.open(fn, "r:ascii-8bit") { |f| f.read }
206
+ File.open(filename, "r:ascii-8bit") { |f| f.read }
197
207
  else
198
- File.read fn
208
+ File.read filename
199
209
  end
200
210
 
201
- if /coding:\s*(\S+)/ =~ content[/\A(?:.*\n){0,2}/]
202
- if enc = Encoding.find($1)
203
- content.force_encoding(enc)
211
+ if defined? Encoding then
212
+ if /coding:\s*(\S+)/ =~ content[/\A(?:.*\n){0,2}/]
213
+ if enc = ::Encoding.find($1)
214
+ content.force_encoding(enc)
215
+ end
204
216
  end
205
217
  end
206
218
 
207
- top_level = TopLevel.new(fn)
208
- parser = ParserFactory.parser_for(top_level, fn, content, options, @stats)
219
+ top_level = ::RDoc::TopLevel.new filename
220
+
221
+ parser = ::RDoc::Parser.for top_level, filename, content, options,
222
+ @stats
223
+
209
224
  file_info << parser.scan
210
- @stats.num_files += 1
211
225
  end
212
226
 
213
227
  file_info
@@ -241,17 +255,19 @@ module RDoc
241
255
 
242
256
  file_info = parse_files @options
243
257
 
258
+ @options.title = "RDoc Documentation"
259
+
244
260
  if file_info.empty?
245
261
  $stderr.puts "\nNo newer files." unless @options.quiet
246
262
  else
247
- gen = @options.generator
263
+ @gen = @options.generator
248
264
 
249
- $stderr.puts "\nGenerating #{gen.key.upcase}..." unless @options.quiet
265
+ $stderr.puts "\nGenerating #{@gen.key.upcase}..." unless @options.quiet
250
266
 
251
- require gen.file_name
267
+ require @gen.file_name
252
268
 
253
- gen_class = ::RDoc::Generator.const_get gen.class_name
254
- gen = gen_class.for @options
269
+ gen_class = ::RDoc::Generator.const_get @gen.class_name
270
+ @gen = gen_class.for @options
255
271
 
256
272
  pwd = Dir.pwd
257
273
 
@@ -259,7 +275,7 @@ module RDoc
259
275
 
260
276
  begin
261
277
  Diagram.new(file_info, @options).draw if @options.diagram
262
- gen.generate(file_info)
278
+ @gen.generate(file_info)
263
279
  update_output_dir(".", start_time)
264
280
  ensure
265
281
  Dir.chdir(pwd)
@@ -1,4 +1,8 @@
1
1
  require 'rdoc'
2
2
 
3
- module RDoc::RI; end
3
+ module RDoc::RI
4
+
5
+ class Error < RDoc::Error; end
6
+
7
+ end
4
8
 
@@ -2,11 +2,10 @@ require 'yaml'
2
2
  require 'rdoc/markup/fragments'
3
3
  require 'rdoc/ri'
4
4
 
5
- #--
5
+ ##
6
6
  # Descriptions are created by RDoc (in ri_generator) and written out in
7
7
  # serialized form into the documentation tree. ri then reads these to generate
8
8
  # the documentation
9
- #++
10
9
 
11
10
  class RDoc::RI::NamedThing
12
11
  attr_reader :name
@@ -83,7 +82,7 @@ class RDoc::RI::ModuleDescription < RDoc::RI::Description
83
82
  attr_accessor :constants
84
83
  attr_accessor :includes
85
84
 
86
- # merge in another class desscription into this one
85
+ # merge in another class description into this one
87
86
  def merge_in(old)
88
87
  merge(@class_methods, old.class_methods)
89
88
  merge(@instance_methods, old.instance_methods)
@@ -94,8 +93,12 @@ class RDoc::RI::ModuleDescription < RDoc::RI::Description
94
93
  @comment = old.comment
95
94
  else
96
95
  unless old.comment.nil? or old.comment.empty? then
97
- @comment << RDoc::Markup::Flow::RULE.new
98
- @comment.concat old.comment
96
+ if @comment.nil? or @comment.empty? then
97
+ @comment = old.comment
98
+ else
99
+ @comment << RDoc::Markup::Flow::RULE.new
100
+ @comment.concat old.comment
101
+ end
99
102
  end
100
103
  end
101
104
  end
@@ -11,6 +11,64 @@ require 'rdoc/markup/to_flow'
11
11
 
12
12
  class RDoc::RI::Driver
13
13
 
14
+ class Hash < ::Hash
15
+ def self.convert(hash)
16
+ hash = new.update hash
17
+
18
+ hash.each do |key, value|
19
+ hash[key] = case value
20
+ when ::Hash then
21
+ convert value
22
+ when Array then
23
+ value = value.map do |v|
24
+ ::Hash === v ? convert(v) : v
25
+ end
26
+ value
27
+ else
28
+ value
29
+ end
30
+ end
31
+
32
+ hash
33
+ end
34
+
35
+ def method_missing method, *args
36
+ self[method.to_s]
37
+ end
38
+
39
+ def merge_enums(other)
40
+ other.each do |k, v|
41
+ if self[k] then
42
+ case v
43
+ when Array then
44
+ # HACK dunno
45
+ if String === self[k] and self[k].empty? then
46
+ self[k] = v
47
+ else
48
+ self[k] += v
49
+ end
50
+ when Hash then
51
+ self[k].update v
52
+ else
53
+ # do nothing
54
+ end
55
+ else
56
+ self[k] = v
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ class Error < RDoc::RI::Error; end
63
+
64
+ class NotFoundError < Error
65
+ def message
66
+ "Nothing known about #{super}"
67
+ end
68
+ end
69
+
70
+ attr_accessor :homepath # :nodoc:
71
+
14
72
  def self.process_args(argv)
15
73
  options = {}
16
74
  options[:use_stdout] = !$stdout.tty?
@@ -234,7 +292,7 @@ Options may also be set in the 'RI' environment variable.
234
292
  @class_cache = if up_to_date then
235
293
  load_cache_for @class_cache_name
236
294
  else
237
- class_cache = {}
295
+ class_cache = RDoc::RI::Driver::Hash.new
238
296
 
239
297
  classes = map_dirs('**/cdesc*.yaml', :sys) { |f| Dir[f] }
240
298
  populate_class_cache class_cache, classes
@@ -245,6 +303,9 @@ Options may also be set in the 'RI' environment variable.
245
303
  populate_class_cache class_cache, classes, true
246
304
  write_cache class_cache, class_cache_file_path
247
305
  end
306
+
307
+ @class_cache = RDoc::RI::Driver::Hash.convert @class_cache
308
+ @class_cache
248
309
  end
249
310
 
250
311
  def class_cache_file_path
@@ -261,21 +322,29 @@ Options may also be set in the 'RI' environment variable.
261
322
 
262
323
  def display_class(name)
263
324
  klass = class_cache[name]
325
+ klass = RDoc::RI::Driver::Hash.convert klass
264
326
  @display.display_class_info klass, class_cache
265
327
  end
266
328
 
329
+ def get_info_for(arg)
330
+ @names = [arg]
331
+ run
332
+ end
333
+
267
334
  def load_cache_for(klassname)
268
335
  path = cache_file_for klassname
269
336
 
337
+ cache = nil
338
+
270
339
  if File.exist? path and
271
340
  File.mtime(path) >= File.mtime(class_cache_file_path) then
272
- File.open path, 'rb' do |fp|
273
- Marshal.load fp.read
341
+ open path, 'rb' do |fp|
342
+ cache = Marshal.load fp.read
274
343
  end
275
344
  else
276
345
  class_cache = nil
277
346
 
278
- File.open class_cache_file_path, 'rb' do |fp|
347
+ open class_cache_file_path, 'rb' do |fp|
279
348
  class_cache = Marshal.load fp.read
280
349
  end
281
350
 
@@ -283,7 +352,7 @@ Options may also be set in the 'RI' environment variable.
283
352
  return nil unless klass
284
353
 
285
354
  method_files = klass["sources"]
286
- cache = {}
355
+ cache = RDoc::RI::Driver::Hash.new
287
356
 
288
357
  sys_dir = @sys_dirs.first
289
358
  method_files.each do |f|
@@ -296,12 +365,45 @@ Options may also be set in the 'RI' environment variable.
296
365
  ext_path = f
297
366
  ext_path = "gem #{$1}" if f =~ %r%gems/[\d.]+/doc/([^/]+)%
298
367
  method["source_path"] = ext_path unless system_file
299
- cache[name] = method
368
+ cache[name] = RDoc::RI::Driver::Hash.convert method
300
369
  end
301
370
  end
302
371
 
303
372
  write_cache cache, path
304
373
  end
374
+
375
+ RDoc::RI::Driver::Hash.convert cache
376
+ end
377
+
378
+ ##
379
+ # Finds the next ancestor of +orig_klass+ after +klass+.
380
+
381
+ def lookup_ancestor(klass, orig_klass)
382
+ cache = class_cache[orig_klass]
383
+
384
+ return nil unless cache
385
+
386
+ ancestors = [orig_klass]
387
+ ancestors.push(*cache.includes.map { |inc| inc['name'] })
388
+ ancestors << cache.superclass
389
+
390
+ ancestor = ancestors[ancestors.index(klass) + 1]
391
+
392
+ return ancestor if ancestor
393
+
394
+ lookup_ancestor klass, cache.superclass
395
+ end
396
+
397
+ ##
398
+ # Finds the method
399
+
400
+ def lookup_method(name, klass)
401
+ cache = load_cache_for klass
402
+ return nil unless cache
403
+
404
+ method = cache[name.gsub('.', '#')]
405
+ method = cache[name.gsub('.', '::')] unless method
406
+ method
305
407
  end
306
408
 
307
409
  def map_dirs(file_name, system=false)
@@ -318,6 +420,22 @@ Options may also be set in the 'RI' environment variable.
318
420
  dirs.map { |dir| yield File.join(dir, file_name) }.flatten.compact
319
421
  end
320
422
 
423
+ ##
424
+ # Extract the class and method name parts from +name+ like Foo::Bar#baz
425
+
426
+ def parse_name(name)
427
+ parts = name.split(/(::|\#|\.)/)
428
+
429
+ if parts[-2] != '::' or parts.last !~ /^[A-Z]/ then
430
+ meth = parts.pop
431
+ parts.pop
432
+ end
433
+
434
+ klass = parts.join
435
+
436
+ [klass, meth]
437
+ end
438
+
321
439
  def populate_class_cache(class_cache, classes, extension = false)
322
440
  classes.each do |cdesc|
323
441
  desc = read_yaml cdesc
@@ -337,6 +455,8 @@ Options may also be set in the 'RI' environment variable.
337
455
  desc["class_method_extensions"] = desc.delete "class_methods"
338
456
  end
339
457
 
458
+ klass = RDoc::RI::Driver::Hash.convert klass
459
+
340
460
  klass.merge_enums desc
341
461
  klass["sources"] << cdesc
342
462
  end
@@ -351,11 +471,6 @@ Options may also be set in the 'RI' environment variable.
351
471
  YAML.load data
352
472
  end
353
473
 
354
- def get_info_for(arg)
355
- @names = [arg]
356
- run
357
- end
358
-
359
474
  def run
360
475
  if @names.empty? then
361
476
  @display.list_known_classes class_cache.keys.sort
@@ -366,17 +481,26 @@ Options may also be set in the 'RI' environment variable.
366
481
  if class_cache.key? name then
367
482
  display_class name
368
483
  else
369
- meth = nil
484
+ klass, = parse_name name
485
+
486
+ orig_klass = klass
487
+ orig_name = name
488
+
489
+ until klass == 'Kernel' do
490
+ method = lookup_method name, klass
370
491
 
371
- parts = name.split(/::|\#|\./)
372
- meth = parts.pop unless parts.last =~ /^[A-Z]/
373
- klass = parts.join '::'
492
+ break method if method
493
+
494
+ ancestor = lookup_ancestor klass, orig_klass
495
+
496
+ break unless ancestor
497
+
498
+ name = name.sub klass, ancestor
499
+ klass = ancestor
500
+ end
501
+
502
+ raise NotFoundError, orig_name unless method
374
503
 
375
- cache = load_cache_for klass
376
- # HACK Does not support F.n
377
- abort "Nothing known about #{name}" unless cache
378
- method = cache[name.gsub(/\./, '#')]
379
- abort "Nothing known about #{name}" unless method
380
504
  @display.display_method_info method
381
505
  end
382
506
  else
@@ -384,8 +508,9 @@ Options may also be set in the 'RI' environment variable.
384
508
  display_class name
385
509
  else
386
510
  methods = select_methods(/^#{name}/)
511
+
387
512
  if methods.size == 0
388
- abort "Nothing known about #{name}"
513
+ raise NotFoundError, name
389
514
  elsif methods.size == 1
390
515
  @display.display_method_info methods.first
391
516
  else
@@ -395,6 +520,8 @@ Options may also be set in the 'RI' environment variable.
395
520
  end
396
521
  end
397
522
  end
523
+ rescue NotFoundError => e
524
+ abort e.message
398
525
  end
399
526
 
400
527
  def select_methods(pattern)
@@ -422,31 +549,3 @@ Options may also be set in the 'RI' environment variable.
422
549
 
423
550
  end
424
551
 
425
- class Hash # HACK don't add stuff to Hash.
426
- def method_missing method, *args
427
- self[method.to_s]
428
- end
429
-
430
- def merge_enums(other)
431
- other.each do |k,v|
432
- if self[k] then
433
- case v
434
- when Array then
435
- # HACK dunno
436
- if String === self[k] and self[k].empty? then
437
- self[k] = v
438
- else
439
- self[k] += v
440
- end
441
- when Hash then
442
- self[k].merge! v
443
- else
444
- # do nothing
445
- end
446
- else
447
- self[k] = v
448
- end
449
- end
450
- end
451
- end
452
-