rdoc 3.6.1 → 3.7

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 (66) hide show
  1. data.tar.gz.sig +0 -0
  2. data/History.txt +45 -0
  3. data/Manifest.txt +4 -0
  4. data/lib/rdoc.rb +3 -2
  5. data/lib/rdoc/any_method.rb +12 -7
  6. data/lib/rdoc/attr.rb +16 -1
  7. data/lib/rdoc/class_module.rb +156 -42
  8. data/lib/rdoc/code_object.rb +8 -1
  9. data/lib/rdoc/context.rb +75 -29
  10. data/lib/rdoc/generator/markup.rb +3 -1
  11. data/lib/rdoc/generator/ri.rb +3 -2
  12. data/lib/rdoc/generator/template/darkfish/rdoc.css +4 -0
  13. data/lib/rdoc/known_classes.rb +2 -2
  14. data/lib/rdoc/markup.rb +63 -18
  15. data/lib/rdoc/markup/document.rb +43 -4
  16. data/lib/rdoc/markup/formatter.rb +13 -3
  17. data/lib/rdoc/markup/formatter_test_case.rb +13 -3
  18. data/lib/rdoc/markup/indented_paragraph.rb +33 -0
  19. data/lib/rdoc/markup/inline.rb +8 -1
  20. data/lib/rdoc/markup/parser.rb +1 -0
  21. data/lib/rdoc/markup/pre_process.rb +7 -0
  22. data/lib/rdoc/markup/to_ansi.rb +4 -4
  23. data/lib/rdoc/markup/to_bs.rb +1 -1
  24. data/lib/rdoc/markup/to_html.rb +2 -2
  25. data/lib/rdoc/markup/to_html_crossref.rb +3 -2
  26. data/lib/rdoc/markup/to_rdoc.rb +10 -1
  27. data/lib/rdoc/markup/to_test.rb +1 -1
  28. data/lib/rdoc/markup/to_tt_only.rb +1 -1
  29. data/lib/rdoc/parser.rb +1 -1
  30. data/lib/rdoc/parser/c.rb +69 -26
  31. data/lib/rdoc/parser/ruby.rb +19 -9
  32. data/lib/rdoc/rdoc.rb +14 -3
  33. data/lib/rdoc/ri/driver.rb +137 -103
  34. data/lib/rdoc/ri/store.rb +111 -26
  35. data/lib/rdoc/ruby_lex.rb +1 -1
  36. data/lib/rdoc/rubygems_hook.rb +220 -0
  37. data/lib/rdoc/text.rb +1 -1
  38. data/lib/rdoc/top_level.rb +31 -0
  39. data/test/test_rdoc_any_method.rb +68 -0
  40. data/test/test_rdoc_attr.rb +62 -0
  41. data/test/test_rdoc_class_module.rb +459 -29
  42. data/test/test_rdoc_code_object.rb +17 -0
  43. data/test/test_rdoc_context.rb +70 -0
  44. data/test/test_rdoc_context_section.rb +1 -1
  45. data/test/test_rdoc_generator_ri.rb +14 -3
  46. data/test/test_rdoc_markup.rb +55 -1
  47. data/test/test_rdoc_markup_document.rb +83 -0
  48. data/test/test_rdoc_markup_indented_paragraph.rb +40 -0
  49. data/test/test_rdoc_markup_paragraph.rb +12 -0
  50. data/test/test_rdoc_markup_pre_process.rb +13 -2
  51. data/test/test_rdoc_markup_to_ansi.rb +4 -0
  52. data/test/test_rdoc_markup_to_bs.rb +4 -0
  53. data/test/test_rdoc_markup_to_html.rb +7 -3
  54. data/test/test_rdoc_markup_to_rdoc.rb +14 -0
  55. data/test/test_rdoc_markup_to_tt_only.rb +4 -0
  56. data/test/test_rdoc_parser_c.rb +302 -2
  57. data/test/test_rdoc_parser_ruby.rb +48 -1
  58. data/test/test_rdoc_rdoc.rb +41 -10
  59. data/test/test_rdoc_ri_driver.rb +40 -7
  60. data/test/test_rdoc_ri_store.rb +111 -23
  61. data/test/test_rdoc_rubygems_hook.rb +201 -0
  62. data/test/test_rdoc_stats.rb +12 -12
  63. data/test/test_rdoc_text.rb +17 -0
  64. data/test/test_rdoc_top_level.rb +35 -0
  65. metadata +18 -14
  66. metadata.gz.sig +0 -0
@@ -350,7 +350,9 @@ class RDoc::Parser::Ruby < RDoc::Parser
350
350
 
351
351
  def get_constant_with_optional_parens
352
352
  skip_tkspace false
353
+
353
354
  nest = 0
355
+
354
356
  while TkLPAREN === (tk = peek_tk) or TkfLPAREN === tk do
355
357
  get_tk
356
358
  skip_tkspace
@@ -631,7 +633,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
631
633
  cls.offset = offset
632
634
  cls.line = line_no
633
635
 
634
- cls.comment = comment if cls.document_self
636
+ cls.add_comment comment, @top_level if cls.document_self
635
637
 
636
638
  @top_level.add_to_classes_or_modules cls
637
639
  @stats.add_class cls
@@ -650,7 +652,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
650
652
  other.offset = offset
651
653
  other.line = line_no
652
654
 
653
- other.comment = comment
655
+ other.add_comment comment, @top_level
654
656
  end
655
657
 
656
658
  # notify :nodoc: all if not a constant-named class/module
@@ -826,14 +828,19 @@ class RDoc::Parser::Ruby < RDoc::Parser
826
828
  ##
827
829
  # Parses an +include+ in +context+ with +comment+
828
830
 
829
- def parse_include(context, comment)
831
+ def parse_include context, comment
830
832
  loop do
831
833
  skip_tkspace_comment
832
834
 
833
835
  name = get_constant_with_optional_parens
834
- context.add_include RDoc::Include.new(name, comment) unless name.empty?
836
+
837
+ unless name.empty? then
838
+ incl = context.add_include RDoc::Include.new(name, comment)
839
+ incl.record_location @top_level
840
+ end
835
841
 
836
842
  return unless TkCOMMA === peek_tk
843
+
837
844
  get_tk
838
845
  end
839
846
  end
@@ -1231,7 +1238,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
1231
1238
  mod.record_location @top_level
1232
1239
 
1233
1240
  read_documentation_modifiers mod, RDoc::CLASS_MODIFIERS
1234
- mod.comment = comment if mod.document_self
1241
+ mod.add_comment comment, @top_level if mod.document_self
1235
1242
  parse_statements(mod)
1236
1243
 
1237
1244
  @top_level.add_to_classes_or_modules mod
@@ -1295,9 +1302,12 @@ class RDoc::Parser::Ruby < RDoc::Parser
1295
1302
  while TkCOMMENT === tk do
1296
1303
  comment << tk.text << "\n"
1297
1304
 
1298
- tk = get_tk # this is the newline
1299
- skip_tkspace false # leading spaces
1300
1305
  tk = get_tk
1306
+
1307
+ if TkNL === tk then
1308
+ skip_tkspace false # leading spaces
1309
+ tk = get_tk
1310
+ end
1301
1311
  end
1302
1312
 
1303
1313
  unless comment.empty? then
@@ -1313,7 +1323,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
1313
1323
  non_comment_seen = true
1314
1324
  end
1315
1325
 
1316
- unget_tk tk
1326
+ unget_tk tk # TODO peek instead of get then unget
1317
1327
  keep_comment = true
1318
1328
 
1319
1329
  when TkCLASS then
@@ -1560,7 +1570,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
1560
1570
  else
1561
1571
  new_methods = []
1562
1572
 
1563
- case vis_type
1573
+ case vis_type
1564
1574
  when 'module_function' then
1565
1575
  args = parse_symbol_arg
1566
1576
  container.set_visibility_for args, :private, false
@@ -100,6 +100,14 @@ class RDoc::RDoc
100
100
  @current = rdoc
101
101
  end
102
102
 
103
+ ##
104
+ # Resets all internal state
105
+
106
+ def self.reset
107
+ RDoc::TopLevel.reset
108
+ RDoc::Parser::C.reset
109
+ end
110
+
103
111
  ##
104
112
  # Creates a new RDoc::RDoc instance. Call #document to parse files and
105
113
  # generate documentation.
@@ -306,8 +314,12 @@ option)
306
314
  # Parses +filename+ and returns an RDoc::TopLevel
307
315
 
308
316
  def parse_file filename
317
+ if defined?(Encoding) then
318
+ encoding = @options.encoding
319
+ filename = filename.encode encoding
320
+ end
321
+
309
322
  @stats.add_file filename
310
- encoding = @options.encoding if defined?(Encoding)
311
323
 
312
324
  content = RDoc::Encoding.read_file filename, encoding
313
325
 
@@ -396,8 +408,7 @@ The internal error was:
396
408
  # current directory, so make sure you're somewhere writable before invoking.
397
409
 
398
410
  def document options
399
- RDoc::TopLevel.reset
400
- RDoc::Parser::C.reset
411
+ RDoc::RDoc.reset
401
412
 
402
413
  if RDoc::Options === options then
403
414
  @options = options
@@ -344,8 +344,8 @@ Options may also be set in the 'RI' environment variable.
344
344
  @stores = []
345
345
 
346
346
  RDoc::RI::Paths.each(options[:use_system], options[:use_site],
347
- options[:use_home], options[:use_gems],
348
- *options[:extra_doc_dirs]) do |path, type|
347
+ options[:use_home], options[:use_gems],
348
+ *options[:extra_doc_dirs]) do |path, type|
349
349
  @doc_dirs << path
350
350
 
351
351
  store = RDoc::RI::Store.new path, type
@@ -456,9 +456,13 @@ Options may also be set in the 'RI' environment variable.
456
456
  out << RDoc::Markup::Heading.new(1, "#{name}:")
457
457
  out << RDoc::Markup::BlankLine.new
458
458
 
459
- out.push(*methods.map do |method|
460
- RDoc::Markup::Verbatim.new method
461
- end)
459
+ if @use_stdout and !@interactive
460
+ out.push(*methods.map do |method|
461
+ RDoc::Markup::Verbatim.new method
462
+ end)
463
+ else
464
+ out << RDoc::Markup::IndentedParagraph.new(2, methods.join(', '))
465
+ end
462
466
 
463
467
  out << RDoc::Markup::BlankLine.new
464
468
  end
@@ -500,6 +504,70 @@ Options may also be set in the 'RI' environment variable.
500
504
  def class_cache # :nodoc:
501
505
  end
502
506
 
507
+ ##
508
+ # Builds a RDoc::Markup::Document from +found+, +klasess+ and +includes+
509
+
510
+ def class_document name, found, klasses, includes
511
+ also_in = []
512
+
513
+ out = RDoc::Markup::Document.new
514
+
515
+ add_class out, name, klasses
516
+
517
+ add_includes out, includes
518
+
519
+ found.each do |store, klass|
520
+ comment = klass.comment
521
+ class_methods = store.class_methods[klass.full_name]
522
+ instance_methods = store.instance_methods[klass.full_name]
523
+ attributes = store.attributes[klass.full_name]
524
+
525
+ if comment.empty? and !(instance_methods or class_methods) then
526
+ also_in << store
527
+ next
528
+ end
529
+
530
+ add_from out, store
531
+
532
+ unless comment.empty? then
533
+ out << RDoc::Markup::Rule.new(1)
534
+ out << comment
535
+ end
536
+
537
+ if class_methods or instance_methods or not klass.constants.empty? then
538
+ out << RDoc::Markup::Rule.new(1)
539
+ end
540
+
541
+ unless klass.constants.empty? then
542
+ out << RDoc::Markup::Heading.new(1, "Constants:")
543
+ out << RDoc::Markup::BlankLine.new
544
+ list = RDoc::Markup::List.new :NOTE
545
+
546
+ constants = klass.constants.sort_by { |constant| constant.name }
547
+
548
+ list.push(*constants.map do |constant|
549
+ parts = constant.comment.parts if constant.comment
550
+ parts << RDoc::Markup::Paragraph.new('[not documented]') if
551
+ parts.empty?
552
+
553
+ RDoc::Markup::ListItem.new(constant.name, *parts)
554
+ end)
555
+
556
+ out << list
557
+ end
558
+
559
+ add_method_list out, class_methods, 'Class methods'
560
+ add_method_list out, instance_methods, 'Instance methods'
561
+ add_method_list out, attributes, 'Attributes'
562
+
563
+ out << RDoc::Markup::BlankLine.new
564
+ end
565
+
566
+ add_also_in out, also_in
567
+
568
+ out
569
+ end
570
+
503
571
  ##
504
572
  # Hash mapping a known class or module to the stores it can be loaded from
505
573
 
@@ -519,6 +587,29 @@ Options may also be set in the 'RI' environment variable.
519
587
  @classes
520
588
  end
521
589
 
590
+ ##
591
+ # Returns the stores wherin +name+ is found along with the classes and
592
+ # includes that match it
593
+
594
+ def classes_and_includes_for name
595
+ klasses = []
596
+ includes = []
597
+
598
+ found = @stores.map do |store|
599
+ begin
600
+ klass = store.load_class name
601
+ klasses << klass
602
+ includes << [klass.includes, store] if klass.includes
603
+ [store, klass]
604
+ rescue Errno::ENOENT
605
+ end
606
+ end.compact
607
+
608
+ includes.reject! do |modules,| modules.empty? end
609
+
610
+ [found, klasses, includes]
611
+ end
612
+
522
613
  ##
523
614
  # Completes +name+ based on the caches. For Readline
524
615
 
@@ -532,8 +623,9 @@ Options may also be set in the 'RI' environment variable.
532
623
  klass_name = method ? name : klass
533
624
 
534
625
  if name !~ /#|\./ then
535
- completions = klasses.grep(/^#{klass_name}[^:]*$/)
536
- completions.concat klasses.grep(/^#{name}[^:]*$/) if name =~ /::$/
626
+ completions = klasses.grep(/^#{Regexp.escape klass_name}[^:]*$/)
627
+ completions.concat klasses.grep(/^#{Regexp.escape name}[^:]*$/) if
628
+ name =~ /::$/
537
629
 
538
630
  completions << klass if classes.key? klass # to complete a method name
539
631
  elsif selector then
@@ -577,79 +669,11 @@ Options may also be set in the 'RI' environment variable.
577
669
  def display_class name
578
670
  return if name =~ /#|\./
579
671
 
580
- klasses = []
581
- includes = []
582
-
583
- found = @stores.map do |store|
584
- begin
585
- klass = store.load_class name
586
- klasses << klass
587
- includes << [klass.includes, store] if klass.includes
588
- [store, klass]
589
- rescue Errno::ENOENT
590
- end
591
- end.compact
672
+ found, klasses, includes = classes_and_includes_for name
592
673
 
593
674
  return if found.empty?
594
675
 
595
- also_in = []
596
-
597
- includes.reject! do |modules,| modules.empty? end
598
-
599
- out = RDoc::Markup::Document.new
600
-
601
- add_class out, name, klasses
602
-
603
- add_includes out, includes
604
-
605
- found.each do |store, klass|
606
- comment = klass.comment
607
- class_methods = store.class_methods[klass.full_name]
608
- instance_methods = store.instance_methods[klass.full_name]
609
- attributes = store.attributes[klass.full_name]
610
-
611
- if comment.empty? and !(instance_methods or class_methods) then
612
- also_in << store
613
- next
614
- end
615
-
616
- add_from out, store
617
-
618
- unless comment.empty? then
619
- out << RDoc::Markup::Rule.new(1)
620
- out << comment
621
- end
622
-
623
- if class_methods or instance_methods or not klass.constants.empty? then
624
- out << RDoc::Markup::Rule.new(1)
625
- end
626
-
627
- unless klass.constants.empty? then
628
- out << RDoc::Markup::Heading.new(1, "Constants:")
629
- out << RDoc::Markup::BlankLine.new
630
- list = RDoc::Markup::List.new :NOTE
631
-
632
- constants = klass.constants.sort_by { |constant| constant.name }
633
-
634
- list.push(*constants.map do |constant|
635
- parts = constant.comment.parts if constant.comment
636
- parts << RDoc::Markup::Paragraph.new('[not documented]') if
637
- parts.empty?
638
-
639
- RDoc::Markup::ListItem.new(constant.name, *parts)
640
- end)
641
-
642
- out << list
643
- end
644
-
645
- add_method_list out, class_methods, 'Class methods'
646
- add_method_list out, instance_methods, 'Instance methods'
647
- add_method_list out, attributes, 'Attributes'
648
-
649
- out << RDoc::Markup::BlankLine.new
650
- end
651
-
652
- add_also_in out, also_in
676
+ out = class_document name, found, klasses, includes
653
677
 
654
678
  display out
655
679
  end
@@ -664,32 +688,7 @@ Options may also be set in the 'RI' environment variable.
664
688
 
665
689
  filtered = filter_methods found, name
666
690
 
667
- out = RDoc::Markup::Document.new
668
-
669
- out << RDoc::Markup::Heading.new(1, name)
670
- out << RDoc::Markup::BlankLine.new
671
-
672
- filtered.each do |store, methods|
673
- methods.each do |method|
674
- out << RDoc::Markup::Paragraph.new("(from #{store.friendly_path})")
675
-
676
- unless name =~ /^#{Regexp.escape method.parent_name}/ then
677
- out << RDoc::Markup::Heading.new(3, "Implementation from #{method.parent_name}")
678
- end
679
- out << RDoc::Markup::Rule.new(1)
680
-
681
- if method.arglists then
682
- arglists = method.arglists.chomp.split "\n"
683
- arglists = arglists.map { |line| line + "\n" }
684
- out << RDoc::Markup::Verbatim.new(*arglists)
685
- out << RDoc::Markup::Rule.new(1)
686
- end
687
-
688
- out << RDoc::Markup::BlankLine.new
689
- out << method.comment
690
- out << RDoc::Markup::BlankLine.new
691
- end
692
- end
691
+ out = method_document name, filtered
693
692
 
694
693
  display out
695
694
  end
@@ -731,6 +730,7 @@ Options may also be set in the 'RI' environment variable.
731
730
  display_name name
732
731
  end
733
732
  end
733
+
734
734
  ##
735
735
  # Expands abbreviated klass +klass+ into a fully-qualified class. "Zl::Da"
736
736
  # will be expanded to Zlib::DataError.
@@ -998,6 +998,40 @@ Options may also be set in the 'RI' environment variable.
998
998
  found.reject do |path, methods| methods.empty? end
999
999
  end
1000
1000
 
1001
+ ##
1002
+ # Builds a RDoc::Markup::Document from +found+, +klasess+ and +includes+
1003
+
1004
+ def method_document name, filtered
1005
+ out = RDoc::Markup::Document.new
1006
+
1007
+ out << RDoc::Markup::Heading.new(1, name)
1008
+ out << RDoc::Markup::BlankLine.new
1009
+
1010
+ filtered.each do |store, methods|
1011
+ methods.each do |method|
1012
+ out << RDoc::Markup::Paragraph.new("(from #{store.friendly_path})")
1013
+
1014
+ unless name =~ /^#{Regexp.escape method.parent_name}/ then
1015
+ out << RDoc::Markup::Heading.new(3, "Implementation from #{method.parent_name}")
1016
+ end
1017
+ out << RDoc::Markup::Rule.new(1)
1018
+
1019
+ if method.arglists then
1020
+ arglists = method.arglists.chomp.split "\n"
1021
+ arglists = arglists.map { |line| line + "\n" }
1022
+ out << RDoc::Markup::Verbatim.new(*arglists)
1023
+ out << RDoc::Markup::Rule.new(1)
1024
+ end
1025
+
1026
+ out << RDoc::Markup::BlankLine.new
1027
+ out << method.comment
1028
+ out << RDoc::Markup::BlankLine.new
1029
+ end
1030
+ end
1031
+
1032
+ out
1033
+ end
1034
+
1001
1035
  ##
1002
1036
  # Returns the type of method (:both, :instance, :class) for +selector+
1003
1037
 
@@ -19,6 +19,8 @@ require 'fileutils'
19
19
  # :modules => [], # classes and modules in this store
20
20
  # :ancestors => {}, # class name => ancestor names
21
21
  # }
22
+ #--
23
+ # TODO need to store the list of files and prune classes
22
24
 
23
25
  class RDoc::RI::Store
24
26
 
@@ -43,20 +45,27 @@ class RDoc::RI::Store
43
45
 
44
46
  attr_reader :cache
45
47
 
48
+ ##
49
+ # The encoding of the contents in the Store
50
+
51
+ attr_accessor :encoding
52
+
46
53
  ##
47
54
  # Creates a new Store of +type+ that will load or save to +path+
48
55
 
49
56
  def initialize path, type = nil
50
- @dry_run = false
51
- @type = type
52
- @path = path
57
+ @dry_run = false
58
+ @type = type
59
+ @path = path
60
+ @encoding = nil
53
61
 
54
62
  @cache = {
63
+ :ancestors => {},
64
+ :attributes => {},
55
65
  :class_methods => {},
66
+ :encoding => @encoding,
56
67
  :instance_methods => {},
57
- :attributes => {},
58
68
  :modules => [],
59
- :ancestors => {},
60
69
  }
61
70
  end
62
71
 
@@ -106,6 +115,22 @@ class RDoc::RI::Store
106
115
  File.join @path, *klass_name.split('::')
107
116
  end
108
117
 
118
+ ##
119
+ # Removes empty items and ensures item in each collection are unique and
120
+ # sorted
121
+
122
+ def clean_cache_collection collection # :nodoc:
123
+ collection.each do |name, item|
124
+ if item.empty? then
125
+ collection.delete name
126
+ else
127
+ # HACK mongrel-1.1.5 documents its files twice
128
+ item.uniq!
129
+ item.sort!
130
+ end
131
+ end
132
+ end
133
+
109
134
  ##
110
135
  # Friendly rendition of #path
111
136
 
@@ -138,9 +163,29 @@ class RDoc::RI::Store
138
163
  # Loads cache file for this store
139
164
 
140
165
  def load_cache
166
+ #orig_enc = @encoding
167
+
141
168
  open cache_path, 'rb' do |io|
142
169
  @cache = Marshal.load io.read
143
170
  end
171
+
172
+ load_enc = @cache[:encoding]
173
+
174
+ # TODO this feature will be time-consuming to add:
175
+ # a) Encodings may be incompatible but transcodeable
176
+ # b) Need to warn in the appropriate spots, wherever they may be
177
+ # c) Need to handle cross-cache differences in encodings
178
+ # d) Need to warn when generating into a cache with diffent encodings
179
+ #
180
+ #if orig_enc and load_enc != orig_enc then
181
+ # warn "Cached encoding #{load_enc} is incompatible with #{orig_enc}\n" \
182
+ # "from #{path}/cache.ri" unless
183
+ # Encoding.compatible? orig_enc, load_enc
184
+ #end
185
+
186
+ @encoding = load_enc unless @encoding
187
+
188
+ @cache
144
189
  rescue Errno::ENOENT
145
190
  end
146
191
 
@@ -192,17 +237,21 @@ class RDoc::RI::Store
192
237
  # Writes the cache file for this store
193
238
 
194
239
  def save_cache
195
- # HACK mongrel-1.1.5 documents its files twice
196
- @cache[:ancestors]. each do |_, m| m.uniq!; m.sort! end
197
- @cache[:attributes]. each do |_, m| m.uniq!; m.sort! end
198
- @cache[:class_methods]. each do |_, m| m.uniq!; m.sort! end
199
- @cache[:instance_methods].each do |_, m| m.uniq!; m.sort! end
200
- @cache[:modules].uniq!; @cache[:modules].sort!
240
+ clean_cache_collection @cache[:ancestors]
241
+ clean_cache_collection @cache[:attributes]
242
+ clean_cache_collection @cache[:class_methods]
243
+ clean_cache_collection @cache[:instance_methods]
244
+
245
+ @cache[:modules].uniq!
246
+ @cache[:modules].sort!
247
+ @cache[:encoding] = @encoding # this gets set twice due to assert_cache
201
248
 
202
249
  return if @dry_run
203
250
 
251
+ marshal = Marshal.dump @cache
252
+
204
253
  open cache_path, 'wb' do |io|
205
- Marshal.dump @cache, io
254
+ io.write marshal
206
255
  end
207
256
  end
208
257
 
@@ -210,11 +259,13 @@ class RDoc::RI::Store
210
259
  # Writes the ri data for +klass+
211
260
 
212
261
  def save_class klass
213
- FileUtils.mkdir_p class_path(klass.full_name) unless @dry_run
262
+ full_name = klass.full_name
263
+
264
+ FileUtils.mkdir_p class_path(full_name) unless @dry_run
214
265
 
215
- @cache[:modules] << klass.full_name
266
+ @cache[:modules] << full_name
216
267
 
217
- path = class_file klass.full_name
268
+ path = class_file full_name
218
269
 
219
270
  begin
220
271
  disk_klass = nil
@@ -223,7 +274,7 @@ class RDoc::RI::Store
223
274
  disk_klass = Marshal.load io.read
224
275
  end
225
276
 
226
- klass.merge disk_klass
277
+ klass = disk_klass.merge klass
227
278
  rescue Errno::ENOENT
228
279
  end
229
280
 
@@ -233,22 +284,52 @@ class RDoc::RI::Store
233
284
  String === ancestor ? ancestor : ancestor.full_name
234
285
  end
235
286
 
236
- @cache[:ancestors][klass.full_name] ||= []
237
- @cache[:ancestors][klass.full_name].push(*ancestors)
287
+ @cache[:ancestors][full_name] ||= []
288
+ @cache[:ancestors][full_name].push(*ancestors)
238
289
 
239
290
  attributes = klass.attributes.map do |attribute|
240
291
  "#{attribute.definition} #{attribute.name}"
241
292
  end
242
293
 
243
294
  unless attributes.empty? then
244
- @cache[:attributes][klass.full_name] ||= []
245
- @cache[:attributes][klass.full_name].push(*attributes)
295
+ @cache[:attributes][full_name] ||= []
296
+ @cache[:attributes][full_name].push(*attributes)
297
+ end
298
+
299
+ to_delete = []
300
+
301
+ unless klass.method_list.empty? then
302
+ @cache[:class_methods][full_name] ||= []
303
+ @cache[:instance_methods][full_name] ||= []
304
+
305
+ class_methods, instance_methods =
306
+ klass.method_list.partition { |meth| meth.singleton }
307
+
308
+ class_methods = class_methods. map { |method| method.name }
309
+ instance_methods = instance_methods.map { |method| method.name }
310
+
311
+ old = @cache[:class_methods][full_name] - class_methods
312
+ to_delete.concat old.map { |method|
313
+ method_file full_name, "#{full_name}::#{method}"
314
+ }
315
+
316
+ old = @cache[:instance_methods][full_name] - instance_methods
317
+ to_delete.concat old.map { |method|
318
+ method_file full_name, "#{full_name}##{method}"
319
+ }
320
+
321
+ @cache[:class_methods][full_name] = class_methods
322
+ @cache[:instance_methods][full_name] = instance_methods
246
323
  end
247
324
 
248
325
  return if @dry_run
249
326
 
327
+ FileUtils.rm_f to_delete
328
+
329
+ marshal = Marshal.dump klass
330
+
250
331
  open path, 'wb' do |io|
251
- Marshal.dump klass, io
332
+ io.write marshal
252
333
  end
253
334
  end
254
335
 
@@ -256,20 +337,24 @@ class RDoc::RI::Store
256
337
  # Writes the ri data for +method+ on +klass+
257
338
 
258
339
  def save_method klass, method
259
- FileUtils.mkdir_p class_path(klass.full_name) unless @dry_run
340
+ full_name = klass.full_name
341
+
342
+ FileUtils.mkdir_p class_path(full_name) unless @dry_run
260
343
 
261
344
  cache = if method.singleton then
262
345
  @cache[:class_methods]
263
346
  else
264
347
  @cache[:instance_methods]
265
348
  end
266
- cache[klass.full_name] ||= []
267
- cache[klass.full_name] << method.name
349
+ cache[full_name] ||= []
350
+ cache[full_name] << method.name
268
351
 
269
352
  return if @dry_run
270
353
 
271
- open method_file(klass.full_name, method.full_name), 'wb' do |io|
272
- Marshal.dump method, io
354
+ marshal = Marshal.dump method
355
+
356
+ open method_file(full_name, method.full_name), 'wb' do |io|
357
+ io.write marshal
273
358
  end
274
359
  end
275
360