rdoc 7.2.0 → 8.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +4 -7
  3. data/LICENSE.rdoc +4 -0
  4. data/README.md +43 -2
  5. data/RI.md +75 -75
  6. data/doc/markup_reference/markdown.md +104 -3
  7. data/exe/rdoc +2 -2
  8. data/lib/rdoc/code_object/alias.rb +70 -74
  9. data/lib/rdoc/code_object/any_method.rb +305 -298
  10. data/lib/rdoc/code_object/attr.rb +150 -143
  11. data/lib/rdoc/code_object/class_module.rb +801 -765
  12. data/lib/rdoc/code_object/constant.rb +178 -150
  13. data/lib/rdoc/code_object/context/section.rb +133 -160
  14. data/lib/rdoc/code_object/context.rb +925 -952
  15. data/lib/rdoc/code_object/extend.rb +7 -5
  16. data/lib/rdoc/code_object/include.rb +7 -5
  17. data/lib/rdoc/code_object/method_attr.rb +325 -324
  18. data/lib/rdoc/code_object/mixin.rb +97 -95
  19. data/lib/rdoc/code_object/normal_class.rb +77 -78
  20. data/lib/rdoc/code_object/normal_module.rb +61 -59
  21. data/lib/rdoc/code_object/require.rb +23 -39
  22. data/lib/rdoc/code_object/single_class.rb +21 -19
  23. data/lib/rdoc/code_object/top_level.rb +212 -213
  24. data/lib/rdoc/code_object.rb +305 -305
  25. data/lib/rdoc/comment.rb +274 -337
  26. data/lib/rdoc/cross_reference.rb +194 -212
  27. data/lib/rdoc/encoding.rb +105 -103
  28. data/lib/rdoc/erb_partial.rb +13 -11
  29. data/lib/rdoc/erbio.rb +29 -27
  30. data/lib/rdoc/generator/aliki.rb +165 -140
  31. data/lib/rdoc/generator/darkfish.rb +647 -631
  32. data/lib/rdoc/generator/json_index.rb +233 -229
  33. data/lib/rdoc/generator/markup.rb +165 -122
  34. data/lib/rdoc/generator/pot/message_extractor.rb +57 -51
  35. data/lib/rdoc/generator/pot/po.rb +52 -51
  36. data/lib/rdoc/generator/pot/po_entry.rb +138 -132
  37. data/lib/rdoc/generator/pot.rb +85 -81
  38. data/lib/rdoc/generator/ri.rb +23 -19
  39. data/lib/rdoc/generator/template/aliki/DESIGN.md +538 -0
  40. data/lib/rdoc/generator/template/aliki/_aside_toc.rhtml +1 -1
  41. data/lib/rdoc/generator/template/aliki/_footer.rhtml +1 -1
  42. data/lib/rdoc/generator/template/aliki/_head.rhtml +11 -11
  43. data/lib/rdoc/generator/template/aliki/_header.rhtml +29 -44
  44. data/lib/rdoc/generator/template/aliki/_sidebar_extends.rhtml +8 -6
  45. data/lib/rdoc/generator/template/aliki/_sidebar_includes.rhtml +8 -6
  46. data/lib/rdoc/generator/template/aliki/_sidebar_installed.rhtml +1 -1
  47. data/lib/rdoc/generator/template/aliki/_sidebar_pages.rhtml +2 -2
  48. data/lib/rdoc/generator/template/aliki/_sidebar_search.rhtml +4 -4
  49. data/lib/rdoc/generator/template/aliki/_sidebar_sections.rhtml +1 -1
  50. data/lib/rdoc/generator/template/aliki/_sidebar_toggle.rhtml +1 -1
  51. data/lib/rdoc/generator/template/aliki/class.rhtml +56 -46
  52. data/lib/rdoc/generator/template/aliki/css/rdoc.css +538 -283
  53. data/lib/rdoc/generator/template/aliki/index.rhtml +1 -1
  54. data/lib/rdoc/generator/template/aliki/js/aliki.js +80 -102
  55. data/lib/rdoc/generator/template/aliki/page.rhtml +1 -1
  56. data/lib/rdoc/generator/template/aliki/servlet_not_found.rhtml +1 -1
  57. data/lib/rdoc/generator/template/aliki/servlet_root.rhtml +2 -2
  58. data/lib/rdoc/generator/template/darkfish/_footer.rhtml +1 -1
  59. data/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml +8 -6
  60. data/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml +8 -6
  61. data/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml +1 -1
  62. data/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml +1 -1
  63. data/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml +1 -1
  64. data/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml +5 -5
  65. data/lib/rdoc/generator/template/darkfish/class.rhtml +18 -21
  66. data/lib/rdoc/generator/template/darkfish/css/rdoc.css +0 -1
  67. data/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml +3 -3
  68. data/lib/rdoc/generator.rb +48 -46
  69. data/lib/rdoc/i18n/locale.rb +99 -95
  70. data/lib/rdoc/i18n/text.rb +109 -105
  71. data/lib/rdoc/i18n.rb +7 -5
  72. data/lib/rdoc/markdown/byte_runtime.rb +80 -0
  73. data/lib/rdoc/markdown.kpeg +30 -21
  74. data/lib/rdoc/markdown.rb +329 -151
  75. data/lib/rdoc/markup/block_quote.rb +12 -8
  76. data/lib/rdoc/markup/document.rb +127 -123
  77. data/lib/rdoc/markup/formatter.rb +215 -221
  78. data/lib/rdoc/markup/heading.rb +1 -4
  79. data/lib/rdoc/markup/include.rb +33 -29
  80. data/lib/rdoc/markup/indented_paragraph.rb +37 -33
  81. data/lib/rdoc/markup/inline_parser.rb +281 -277
  82. data/lib/rdoc/markup/list.rb +80 -88
  83. data/lib/rdoc/markup/list_item.rb +73 -85
  84. data/lib/rdoc/markup/paragraph.rb +23 -19
  85. data/lib/rdoc/markup/parser.rb +501 -497
  86. data/lib/rdoc/markup/pre_process.rb +284 -305
  87. data/lib/rdoc/markup/raw.rb +2 -2
  88. data/lib/rdoc/markup/rule.rb +16 -12
  89. data/lib/rdoc/markup/to_ansi.rb +143 -139
  90. data/lib/rdoc/markup/to_bs.rb +72 -68
  91. data/lib/rdoc/markup/to_html.rb +600 -493
  92. data/lib/rdoc/markup/to_html_crossref.rb +221 -191
  93. data/lib/rdoc/markup/to_html_snippet.rb +232 -227
  94. data/lib/rdoc/markup/to_joined_paragraph.rb +40 -41
  95. data/lib/rdoc/markup/to_label.rb +63 -59
  96. data/lib/rdoc/markup/to_markdown.rb +212 -208
  97. data/lib/rdoc/markup/to_rdoc.rb +336 -332
  98. data/lib/rdoc/markup/to_table_of_contents.rb +66 -62
  99. data/lib/rdoc/markup/to_test.rb +60 -56
  100. data/lib/rdoc/markup/to_tt_only.rb +83 -86
  101. data/lib/rdoc/markup/verbatim.rb +62 -58
  102. data/lib/rdoc/markup.rb +198 -196
  103. data/lib/rdoc/options.rb +1063 -1076
  104. data/lib/rdoc/parser/c.rb +1039 -1036
  105. data/lib/rdoc/parser/changelog.rb +319 -315
  106. data/lib/rdoc/parser/markdown.rb +17 -13
  107. data/lib/rdoc/parser/rbs.rb +279 -0
  108. data/lib/rdoc/parser/rd.rb +17 -13
  109. data/lib/rdoc/parser/ruby.rb +1231 -2222
  110. data/lib/rdoc/parser/ruby_colorizer.rb +303 -0
  111. data/lib/rdoc/parser/simple.rb +31 -27
  112. data/lib/rdoc/parser/text.rb +12 -8
  113. data/lib/rdoc/parser.rb +230 -221
  114. data/lib/rdoc/rbs_helper.rb +186 -0
  115. data/lib/rdoc/rd/inline.rb +57 -53
  116. data/lib/rdoc/rd.rb +90 -88
  117. data/lib/rdoc/rdoc.rb +547 -366
  118. data/lib/rdoc/ri/driver.rb +1141 -1130
  119. data/lib/rdoc/ri/formatter.rb +7 -3
  120. data/lib/rdoc/ri/paths.rb +140 -136
  121. data/lib/rdoc/ri/servlet.rb +456 -0
  122. data/lib/rdoc/ri/store.rb +4 -2
  123. data/lib/rdoc/ri/task.rb +55 -51
  124. data/lib/rdoc/ri.rb +14 -11
  125. data/lib/rdoc/rubygems_hook.rb +194 -192
  126. data/lib/rdoc/server.rb +462 -0
  127. data/lib/rdoc/stats/normal.rb +46 -42
  128. data/lib/rdoc/stats/quiet.rb +39 -35
  129. data/lib/rdoc/stats/verbose.rb +35 -31
  130. data/lib/rdoc/stats.rb +363 -338
  131. data/lib/rdoc/store.rb +919 -725
  132. data/lib/rdoc/task.rb +260 -255
  133. data/lib/rdoc/text.rb +130 -245
  134. data/lib/rdoc/token_stream.rb +101 -115
  135. data/lib/rdoc/tom_doc.rb +203 -201
  136. data/lib/rdoc/version.rb +1 -1
  137. data/lib/rdoc.rb +35 -7
  138. data/lib/rubygems_plugin.rb +2 -11
  139. data/rdoc-logo.svg +43 -0
  140. data/rdoc.gemspec +6 -4
  141. metadata +36 -20
  142. data/lib/rdoc/code_object/anon_class.rb +0 -10
  143. data/lib/rdoc/code_object/ghost_method.rb +0 -6
  144. data/lib/rdoc/code_object/meta_method.rb +0 -6
  145. data/lib/rdoc/markdown/literals.kpeg +0 -21
  146. data/lib/rdoc/markdown/literals.rb +0 -454
  147. data/lib/rdoc/parser/prism_ruby.rb +0 -1112
  148. data/lib/rdoc/parser/ripper_state_lex.rb +0 -302
  149. data/lib/rdoc/parser/ruby_tools.rb +0 -163
  150. data/lib/rdoc/servlet.rb +0 -452
data/lib/rdoc/store.rb CHANGED
@@ -1,997 +1,1191 @@
1
1
  # frozen_string_literal: true
2
2
  require 'fileutils'
3
3
 
4
- ##
5
- # A set of rdoc data for a single project (gem, path, etc.).
6
- #
7
- # The store manages reading and writing ri data for a project and maintains a
8
- # cache of methods, classes and ancestors in the store.
9
- #
10
- # The store maintains a #cache of its contents for faster lookup. After
11
- # adding items to the store it must be flushed using #save_cache. The cache
12
- # contains the following structures:
13
- #
14
- # @cache = {
15
- # :ancestors => {}, # class name => ancestor names
16
- # :attributes => {}, # class name => attributes
17
- # :class_methods => {}, # class name => class methods
18
- # :instance_methods => {}, # class name => instance methods
19
- # :modules => [], # classes and modules in this store
20
- # :pages => [], # page names
21
- # }
22
- #--
23
- # TODO need to prune classes
24
-
25
- class RDoc::Store
26
-
4
+ module RDoc
27
5
  ##
28
- # Errors raised from loading or saving the store
6
+ # A set of rdoc data for a single project (gem, path, etc.).
7
+ #
8
+ # The store manages reading and writing ri data for a project and maintains a
9
+ # cache of methods, classes and ancestors in the store.
10
+ #
11
+ # The store maintains a #cache of its contents for faster lookup. After
12
+ # adding items to the store it must be flushed using #save_cache. The cache
13
+ # contains the following structures:
14
+ #
15
+ # @cache = {
16
+ # :ancestors => {}, # class name => ancestor names
17
+ # :attributes => {}, # class name => attributes
18
+ # :class_methods => {}, # class name => class methods
19
+ # :instance_methods => {}, # class name => instance methods
20
+ # :modules => [], # classes and modules in this store
21
+ # :pages => [], # page names
22
+ # }
23
+ #--
24
+ # TODO need to prune classes
29
25
 
30
- class Error < RDoc::Error
31
- end
26
+ class Store
32
27
 
33
- ##
34
- # Raised when a stored file for a class, module, page or method is missing.
28
+ ##
29
+ # Errors raised from loading or saving the store
35
30
 
36
- class MissingFileError < Error
31
+ class Error < ::RDoc::Error
32
+ end
37
33
 
38
34
  ##
39
- # The store the file should exist in
35
+ # Raised when a stored file for a class, module, page or method is missing.
40
36
 
41
- attr_reader :store
37
+ class MissingFileError < Error
42
38
 
43
- ##
44
- # The file the #name should be saved as
39
+ ##
40
+ # The store the file should exist in
45
41
 
46
- attr_reader :file
42
+ attr_reader :store
47
43
 
48
- ##
49
- # The name of the object the #file would be loaded from
44
+ ##
45
+ # The file the #name should be saved as
50
46
 
51
- attr_reader :name
47
+ attr_reader :file
52
48
 
53
- ##
54
- # Creates a new MissingFileError for the missing +file+ for the given
55
- # +name+ that should have been in the +store+.
49
+ ##
50
+ # The name of the object the #file would be loaded from
56
51
 
57
- def initialize(store, file, name)
58
- @store = store
59
- @file = file
60
- @name = name
61
- end
52
+ attr_reader :name
53
+
54
+ ##
55
+ # Creates a new MissingFileError for the missing +file+ for the given
56
+ # +name+ that should have been in the +store+.
57
+
58
+ def initialize(store, file, name)
59
+ @store = store
60
+ @file = file
61
+ @name = name
62
+ end
63
+
64
+ def message # :nodoc:
65
+ "store at #{@store.path} missing file #{@file} for #{@name}"
66
+ end
62
67
 
63
- def message # :nodoc:
64
- "store at #{@store.path} missing file #{@file} for #{@name}"
65
68
  end
66
69
 
67
- end
70
+ ##
71
+ # Stores the name of the C variable a class belongs to. This helps wire up
72
+ # classes defined from C across files.
68
73
 
69
- ##
70
- # Stores the name of the C variable a class belongs to. This helps wire up
71
- # classes defined from C across files.
74
+ attr_reader :c_enclosure_classes # :nodoc:
72
75
 
73
- attr_reader :c_enclosure_classes # :nodoc:
76
+ attr_reader :c_enclosure_names # :nodoc:
74
77
 
75
- attr_reader :c_enclosure_names # :nodoc:
78
+ ##
79
+ # Maps C variables to class or module names for each parsed C file.
76
80
 
77
- ##
78
- # Maps C variables to class or module names for each parsed C file.
81
+ attr_reader :c_class_variables
79
82
 
80
- attr_reader :c_class_variables
83
+ ##
84
+ # Maps C variables to singleton class names for each parsed C file.
81
85
 
82
- ##
83
- # Maps C variables to singleton class names for each parsed C file.
86
+ attr_reader :c_singleton_class_variables
84
87
 
85
- attr_reader :c_singleton_class_variables
88
+ ##
89
+ # If true this Store will not write any files
86
90
 
87
- ##
88
- # If true this Store will not write any files
91
+ attr_accessor :dry_run
89
92
 
90
- attr_accessor :dry_run
93
+ ##
94
+ # Path this store reads or writes
91
95
 
92
- ##
93
- # Path this store reads or writes
96
+ attr_accessor :path
94
97
 
95
- attr_accessor :path
98
+ attr_reader :options
96
99
 
97
- attr_reader :options
100
+ ##
101
+ # Type of ri datastore this was loaded from. See RDoc::RI::Driver,
102
+ # RDoc::RI::Paths.
98
103
 
99
- ##
100
- # Type of ri datastore this was loaded from. See RDoc::RI::Driver,
101
- # RDoc::RI::Paths.
104
+ attr_accessor :type
102
105
 
103
- attr_accessor :type
106
+ ##
107
+ # The contents of the Store
104
108
 
105
- ##
106
- # The contents of the Store
109
+ attr_reader :cache
107
110
 
108
- attr_reader :cache
111
+ ##
112
+ # The encoding of the contents in the Store
109
113
 
110
- ##
111
- # The encoding of the contents in the Store
114
+ attr_accessor :encoding
112
115
 
113
- attr_accessor :encoding
116
+ ##
117
+ # Creates a new Store of +type+ that will load or save to +path+
118
+
119
+ def initialize(options, path: nil, type: nil)
120
+ @options = options
121
+ @dry_run = options.dry_run
122
+ @encoding = options.encoding
123
+ @path = path || options.op_dir
124
+ @type = type
125
+
126
+ @cache = {
127
+ :ancestors => {},
128
+ :attributes => {},
129
+ :class_methods => {},
130
+ :c_class_variables => {},
131
+ :c_singleton_class_variables => {},
132
+ :encoding => @encoding,
133
+ :instance_methods => {},
134
+ :main => options.main_page,
135
+ :modules => [],
136
+ :pages => [],
137
+ :title => options.title,
138
+ }
114
139
 
115
- ##
116
- # The lazy constants alias will be discovered in passing
140
+ @classes_hash = {}
141
+ @modules_hash = {}
142
+ @files_hash = {}
117
143
 
118
- attr_reader :unmatched_constant_alias
144
+ @c_enclosure_classes = {}
145
+ @c_enclosure_names = {}
119
146
 
120
- ##
121
- # Creates a new Store of +type+ that will load or save to +path+
122
-
123
- def initialize(options, path: nil, type: nil)
124
- @options = options
125
- @dry_run = options.dry_run
126
- @encoding = options.encoding
127
- @path = path || options.op_dir
128
- @type = type
129
-
130
- @cache = {
131
- :ancestors => {},
132
- :attributes => {},
133
- :class_methods => {},
134
- :c_class_variables => {},
135
- :c_singleton_class_variables => {},
136
- :encoding => @encoding,
137
- :instance_methods => {},
138
- :main => options.main_page,
139
- :modules => [],
140
- :pages => [],
141
- :title => options.title,
142
- }
143
-
144
- @classes_hash = {}
145
- @modules_hash = {}
146
- @files_hash = {}
147
- @text_files_hash = {}
148
-
149
- @c_enclosure_classes = {}
150
- @c_enclosure_names = {}
151
-
152
- @c_class_variables = {}
153
- @c_singleton_class_variables = {}
154
-
155
- @unique_classes = nil
156
- @unique_modules = nil
157
-
158
- @unmatched_constant_alias = {}
159
- end
147
+ @c_class_variables = {}
148
+ @c_singleton_class_variables = {}
160
149
 
161
- ##
162
- # Adds +module+ as an enclosure (namespace) for the given +variable+ for C
163
- # files.
150
+ @unique_classes = nil
151
+ @unique_modules = nil
152
+ end
164
153
 
165
- def add_c_enclosure(variable, namespace)
166
- @c_enclosure_classes[variable] = namespace
167
- end
154
+ ##
155
+ # Adds +module+ as an enclosure (namespace) for the given +variable+ for C
156
+ # files.
168
157
 
169
- ##
170
- # Adds C variables from an RDoc::Parser::C
158
+ def add_c_enclosure(variable, namespace)
159
+ @c_enclosure_classes[variable] = namespace
160
+ end
171
161
 
172
- def add_c_variables(c_parser)
173
- filename = c_parser.top_level.relative_name
162
+ ##
163
+ # Adds C variables from an RDoc::Parser::C
174
164
 
175
- @c_class_variables[filename] = make_variable_map c_parser.classes
165
+ def add_c_variables(c_parser)
166
+ filename = c_parser.top_level.relative_name
176
167
 
177
- @c_singleton_class_variables[filename] = c_parser.singleton_classes
178
- end
168
+ @c_class_variables[filename] = make_variable_map c_parser.classes
179
169
 
180
- ##
181
- # Adds the file with +name+ as an RDoc::TopLevel to the store. Returns the
182
- # created RDoc::TopLevel.
170
+ @c_singleton_class_variables[filename] = c_parser.singleton_classes
171
+ end
172
+
173
+ ##
174
+ # Adds the file with +name+ as an RDoc::TopLevel to the store. Returns the
175
+ # created RDoc::TopLevel.
176
+
177
+ def add_file(absolute_name, relative_name: absolute_name, parser: nil)
178
+ unless top_level = @files_hash[relative_name]
179
+ top_level = TopLevel.new absolute_name, relative_name
180
+ top_level.parser = parser if parser
181
+ top_level.store = self
182
+ @files_hash[relative_name] = top_level
183
+ @page_index = nil
184
+ end
183
185
 
184
- def add_file(absolute_name, relative_name: absolute_name, parser: nil)
185
- unless top_level = @files_hash[relative_name] then
186
- top_level = RDoc::TopLevel.new absolute_name, relative_name
187
- top_level.parser = parser if parser
188
- top_level.store = self
189
- @files_hash[relative_name] = top_level
190
- @text_files_hash[relative_name] = top_level if top_level.text?
186
+ top_level
191
187
  end
192
188
 
193
- top_level
194
- end
189
+ ##
190
+ # Removes a file and its classes/modules from the store. Used by the
191
+ # live-reloading server when a source file is deleted.
192
+ #
193
+ # Note: this does not handle reopened classes correctly. If a class is
194
+ # defined across multiple files (e.g. +Foo+ in both +a.rb+ and +b.rb+),
195
+ # deleting one file removes the entire class from the store — including
196
+ # the parts contributed by the other file. Saving the remaining file
197
+ # triggers a re-parse that restores it.
198
+
199
+ def remove_file(relative_name)
200
+ top_level = @files_hash.delete(relative_name)
201
+ @c_class_variables.delete(relative_name)
202
+ @c_singleton_class_variables.delete(relative_name)
203
+ return unless top_level
204
+
205
+ @page_index = nil
206
+ remove_classes_and_modules(top_level.classes_or_modules)
207
+ end
195
208
 
196
- ##
197
- # Make sure any references to C variable names are resolved to the corresponding class.
198
- #
209
+ ##
210
+ # Removes a file's contributions (methods, constants, comments, etc.)
211
+ # from its classes and modules. If no other files contribute to a
212
+ # class or module, it is removed from the store entirely. This
213
+ # prevents duplication when the file is re-parsed while preserving
214
+ # shared namespaces like +RDoc+ that span many files.
215
+
216
+ def clear_file_contributions(relative_name, keep_position: false)
217
+ top_level = @files_hash[relative_name]
218
+ return unless top_level
219
+
220
+ top_level.classes_or_modules.each do |cm|
221
+ # Remove methods and attributes contributed by this file
222
+ cm.method_list.reject! { |m| m.file == top_level }
223
+ cm.attributes.reject! { |a| a.file == top_level }
224
+
225
+ # Rebuild methods_hash from remaining methods and attributes
226
+ cm.methods_hash.clear
227
+ cm.method_list.each { |m| cm.methods_hash[m.pretty_name] = m }
228
+ cm.attributes.each { |a| cm.methods_hash[a.pretty_name] = a }
229
+
230
+ # Remove constants contributed by this file
231
+ cm.constants.reject! { |c| c.file == top_level }
232
+ cm.constants_hash.clear
233
+ cm.constants.each { |c| cm.constants_hash[c.name] = c }
234
+
235
+ # Remove includes, extends, and aliases from this file
236
+ cm.includes.reject! { |i| i.file == top_level }
237
+ cm.extends.reject! { |e| e.file == top_level }
238
+ cm.aliases.reject! { |a| a.file == top_level }
239
+ cm.external_aliases.reject! { |a| a.file == top_level }
240
+
241
+ # Clear or remove comment entries from this file
242
+ if cm.is_a?(ClassModule)
243
+ if keep_position
244
+ cm.comment_location[top_level] = [] if cm.comment_location.key?(top_level)
245
+ else
246
+ cm.comment_location.delete(top_level)
247
+ end
248
+ cm.rebuild_comment_from_location
249
+ end
199
250
 
200
- def resolve_c_superclasses
201
- @classes_hash.each_value do |klass|
202
- if klass.superclass.is_a?(String) && (candidate = find_c_enclosure(klass.superclass))
203
- klass.superclass = candidate
251
+ unless keep_position
252
+ # Remove this file from the class/module's file list
253
+ cm.in_files.delete(top_level)
254
+
255
+ # If no files contribute to this class/module anymore, remove it
256
+ # from the store entirely. This handles file deletion correctly
257
+ # for classes that are only defined in the deleted file, while
258
+ # preserving classes that span multiple files.
259
+ if cm.in_files.empty?
260
+ if cm.is_a?(NormalModule)
261
+ @modules_hash.delete(cm.full_name)
262
+ else
263
+ @classes_hash.delete(cm.full_name)
264
+ end
265
+ cm.parent&.classes_hash&.delete(cm.name)
266
+ cm.parent&.modules_hash&.delete(cm.name)
267
+ end
268
+ end
204
269
  end
270
+
271
+ # Clear the TopLevel's class/module list to prevent duplicates
272
+ top_level.classes_or_modules.clear
205
273
  end
206
- end
207
274
 
208
- ##
209
- # Sets the parser of +absolute_name+, unless it from a source code file.
275
+ ##
276
+ # Removes stale empty placeholders left by +clear_file_contributions+ with
277
+ # <tt>keep_position: true</tt>. After re-parsing, a file may no longer
278
+ # define a class it previously contributed to, leaving an empty entry in
279
+ # +comment_location+ and a stale +in_files+ reference. Call this after
280
+ # all re-parsing is complete.
281
+
282
+ def cleanup_stale_contributions
283
+ all_classes_and_modules.each do |cm|
284
+ cm.comment_location.delete_if { |_, comments| comments.empty? }
285
+ cm.rebuild_comment_from_location
286
+
287
+ cm.in_files.select! { |tl| cm.comment_location.key?(tl) ||
288
+ cm.method_list.any? { |m| m.file == tl } ||
289
+ cm.attributes.any? { |a| a.file == tl } ||
290
+ cm.constants.any? { |c| c.file == tl } }
291
+
292
+ if cm.in_files.empty?
293
+ if cm.is_a?(NormalModule)
294
+ @modules_hash.delete(cm.full_name)
295
+ else
296
+ @classes_hash.delete(cm.full_name)
297
+ end
298
+ cm.parent&.classes_hash&.delete(cm.name)
299
+ cm.parent&.modules_hash&.delete(cm.name)
300
+ end
301
+ end
302
+ end
303
+
304
+ ##
305
+ # Make sure any references to C variable names are resolved to the corresponding class.
306
+ #
210
307
 
211
- def update_parser_of_file(absolute_name, parser)
212
- if top_level = @files_hash[absolute_name] then
213
- @text_files_hash[absolute_name] = top_level if top_level.text?
308
+ def resolve_c_superclasses
309
+ @classes_hash.each_value do |klass|
310
+ if klass.superclass.is_a?(String) && (candidate = find_c_enclosure(klass.superclass))
311
+ klass.superclass = candidate
312
+ end
313
+ end
214
314
  end
215
- end
216
315
 
217
- ##
218
- # Returns all classes discovered by RDoc
316
+ ##
317
+ # Returns all classes discovered by RDoc
219
318
 
220
- def all_classes
221
- @classes_hash.values
222
- end
319
+ def all_classes
320
+ @classes_hash.values
321
+ end
223
322
 
224
- ##
225
- # Returns all classes and modules discovered by RDoc
323
+ ##
324
+ # Returns all classes and modules discovered by RDoc
226
325
 
227
- def all_classes_and_modules
228
- @classes_hash.values + @modules_hash.values
229
- end
326
+ def all_classes_and_modules
327
+ @classes_hash.values + @modules_hash.values
328
+ end
230
329
 
231
- ##
232
- # All TopLevels known to RDoc
330
+ ##
331
+ # Returns a hash mapping class/module names to their paths, for use
332
+ # by type signature linking. Maps both qualified names (Foo::Bar) and
333
+ # unambiguous unqualified names (Bar). Ambiguous unqualified names
334
+ # (where multiple classes share the same name) are excluded to avoid
335
+ # wrong links. Cached after first call.
233
336
 
234
- def all_files
235
- @files_hash.values
236
- end
337
+ ##
338
+ # Invalidates the cached type name lookup. Server mode calls this after
339
+ # re-parsing changes the set of classes and modules.
237
340
 
238
- ##
239
- # Returns all modules discovered by RDoc
341
+ def invalidate_type_name_lookup # :nodoc:
342
+ @type_name_lookup = nil
343
+ end
240
344
 
241
- def all_modules
242
- modules_hash.values
243
- end
345
+ def type_name_lookup
346
+ @type_name_lookup ||= begin
347
+ lookup = {}
348
+ unqualified_names = {}
349
+ ambiguous_names = {}
350
+ all_classes_and_modules.each do |cm|
351
+ lookup[cm.full_name] = cm.path
352
+ unqualified_name = cm.name
353
+
354
+ if ambiguous_names[unqualified_name]
355
+ # already known ambiguous, skip
356
+ elsif unqualified_names.key?(unqualified_name)
357
+ unqualified_names.delete(unqualified_name)
358
+ ambiguous_names[unqualified_name] = true
359
+ else
360
+ unqualified_names[unqualified_name] = cm.path
361
+ end
362
+ end
363
+ lookup.merge!(unqualified_names)
364
+ end
365
+ end
244
366
 
245
- ##
246
- # Ancestors cache accessor. Maps a klass name to an Array of its ancestors
247
- # in this store. If Foo in this store inherits from Object, Kernel won't be
248
- # listed (it will be included from ruby's ri store).
367
+ ##
368
+ # Stores RBS type signatures loaded from sidecar .rbs files, keyed by
369
+ # "ClassName#method" or "ClassName.method". Replaces any previously
370
+ # stored set, so passing +{}+ clears it. Inline +#:+ annotations on
371
+ # method objects are NOT touched — those are owned by the source file.
249
372
 
250
- def ancestors
251
- @cache[:ancestors]
252
- end
373
+ def merge_rbs_signatures(signatures)
374
+ @rbs_signatures = signatures
375
+ end
253
376
 
254
- ##
255
- # Attributes cache accessor. Maps a class to an Array of its attributes.
377
+ ##
378
+ # Returns the RBS type signature lines for +method_attr+ from loaded
379
+ # sidecar +.rbs+ files, or +nil+ if none. Falls through to the
380
+ # canonical method for aliases, and handles +initialize+ -> +.new+
381
+ # singleton mapping.
382
+
383
+ def rbs_signature_for(method_attr)
384
+ return nil unless @rbs_signatures
385
+ cm = method_attr.parent
386
+ return nil unless cm.respond_to?(:full_name)
387
+
388
+ key = method_attr.singleton ? "#{cm.full_name}.#{method_attr.name}" : "#{cm.full_name}##{method_attr.name}"
389
+ sig = @rbs_signatures[key]
390
+
391
+ # RBS keys constructors as #initialize, but RDoc renames them to .new
392
+ if !sig && method_attr.name == 'new' && method_attr.singleton
393
+ sig = @rbs_signatures["#{cm.full_name}#initialize"]
394
+ end
256
395
 
257
- def attributes
258
- @cache[:attributes]
259
- end
396
+ # For aliases, fall through to the canonical method (its inline #:
397
+ # takes precedence over any sidecar signature on the alias's name).
398
+ if !sig && method_attr.is_alias_for
399
+ canonical = method_attr.is_alias_for
400
+ sig = canonical.type_signature_lines || rbs_signature_for(canonical)
401
+ end
260
402
 
261
- ##
262
- # Path to the cache file
403
+ sig
404
+ end
263
405
 
264
- def cache_path
265
- File.join @path, 'cache.ri'
266
- end
406
+ def clear_rbs_signatures # :nodoc:
407
+ @rbs_signatures = nil
408
+ end
267
409
 
268
- ##
269
- # Path to the ri data for +klass_name+
410
+ ##
411
+ # All TopLevels known to RDoc
270
412
 
271
- def class_file(klass_name)
272
- name = klass_name.split('::').last
273
- File.join class_path(klass_name), "cdesc-#{name}.ri"
274
- end
413
+ def all_files
414
+ @files_hash.values
415
+ end
275
416
 
276
- ##
277
- # Class methods cache accessor. Maps a class to an Array of its class
278
- # methods (not full name).
417
+ ##
418
+ # Returns all modules discovered by RDoc
279
419
 
280
- def class_methods
281
- @cache[:class_methods]
282
- end
420
+ def all_modules
421
+ modules_hash.values
422
+ end
283
423
 
284
- ##
285
- # Path where data for +klass_name+ will be stored (methods or class data)
424
+ ##
425
+ # Ancestors cache accessor. Maps a klass name to an Array of its ancestors
426
+ # in this store. If Foo in this store inherits from Object, Kernel won't be
427
+ # listed (it will be included from ruby's ri store).
286
428
 
287
- def class_path(klass_name)
288
- File.join @path, *klass_name.split('::')
289
- end
429
+ def ancestors
430
+ @cache[:ancestors]
431
+ end
290
432
 
291
- ##
292
- # Hash of all classes known to RDoc
433
+ ##
434
+ # Attributes cache accessor. Maps a class to an Array of its attributes.
293
435
 
294
- def classes_hash
295
- @classes_hash
296
- end
436
+ def attributes
437
+ @cache[:attributes]
438
+ end
297
439
 
298
- ##
299
- # Removes empty items and ensures item in each collection are unique and
300
- # sorted
440
+ ##
441
+ # Path to the cache file
301
442
 
302
- def clean_cache_collection(collection) # :nodoc:
303
- collection.each do |name, item|
304
- if item.empty? then
305
- collection.delete name
306
- else
307
- # HACK mongrel-1.1.5 documents its files twice
308
- item.uniq!
309
- item.sort!
310
- end
443
+ def cache_path
444
+ File.join @path, 'cache.ri'
311
445
  end
312
- end
313
446
 
314
- ##
315
- # Prepares the RDoc code object tree for use by a generator.
316
- #
317
- # It finds unique classes/modules defined, and replaces classes/modules that
318
- # are aliases for another one by a copy with RDoc::ClassModule#is_alias_for
319
- # set.
320
- #
321
- # It updates the RDoc::ClassModule#constant_aliases attribute of "real"
322
- # classes or modules.
323
- #
324
- # It also completely removes the classes and modules that should be removed
325
- # from the documentation and the methods that have a visibility below
326
- # +min_visibility+, which is the <tt>--visibility</tt> option.
327
- #
328
- # See also RDoc::Context#remove_from_documentation?
447
+ ##
448
+ # Path to the ri data for +klass_name+
329
449
 
330
- def complete(min_visibility)
331
- fix_basic_object_inheritance
450
+ def class_file(klass_name)
451
+ name = klass_name.split('::').last
452
+ File.join class_path(klass_name), "cdesc-#{name}.ri"
453
+ end
332
454
 
333
- # cache included modules before they are removed from the documentation
334
- all_classes_and_modules.each { |cm| cm.ancestors }
455
+ ##
456
+ # Class methods cache accessor. Maps a class to an Array of its class
457
+ # methods (not full name).
335
458
 
336
- unless min_visibility == :nodoc then
337
- remove_nodoc @classes_hash
338
- remove_nodoc @modules_hash
459
+ def class_methods
460
+ @cache[:class_methods]
339
461
  end
340
462
 
341
- @unique_classes = find_unique @classes_hash
342
- @unique_modules = find_unique @modules_hash
463
+ ##
464
+ # Path where data for +klass_name+ will be stored (methods or class data)
343
465
 
344
- unique_classes_and_modules.each do |cm|
345
- cm.complete min_visibility
466
+ def class_path(klass_name)
467
+ File.join @path, *klass_name.split('::')
346
468
  end
347
469
 
348
- @files_hash.each_key do |file_name|
349
- tl = @files_hash[file_name]
470
+ ##
471
+ # Hash of all classes known to RDoc
350
472
 
351
- unless tl.text? then
352
- tl.modules_hash.clear
353
- tl.classes_hash.clear
473
+ def classes_hash
474
+ @classes_hash
475
+ end
354
476
 
355
- tl.classes_or_modules.each do |cm|
356
- name = cm.full_name
357
- if cm.type == 'class' then
358
- tl.classes_hash[name] = cm if @classes_hash[name]
359
- else
360
- tl.modules_hash[name] = cm if @modules_hash[name]
361
- end
477
+ ##
478
+ # Removes empty items and ensures item in each collection are unique and
479
+ # sorted
480
+
481
+ def clean_cache_collection(collection) # :nodoc:
482
+ collection.each do |name, item|
483
+ if item.empty?
484
+ collection.delete name
485
+ else
486
+ # HACK mongrel-1.1.5 documents its files twice
487
+ item.uniq!
488
+ item.sort!
362
489
  end
363
490
  end
364
491
  end
365
- end
366
-
367
- ##
368
- # Hash of all files known to RDoc
369
492
 
370
- def files_hash
371
- @files_hash
372
- end
493
+ ##
494
+ # Prepares the RDoc code object tree for use by a generator.
495
+ #
496
+ # It finds unique classes/modules defined, and replaces classes/modules that
497
+ # are aliases for another one by a copy with RDoc::ClassModule#is_alias_for
498
+ # set.
499
+ #
500
+ # It updates the RDoc::ClassModule#constant_aliases attribute of "real"
501
+ # classes or modules.
502
+ #
503
+ # It also completely removes the classes and modules that should be removed
504
+ # from the documentation and the methods that have a visibility below
505
+ # +min_visibility+, which is the <tt>--visibility</tt> option.
506
+ #
507
+ # See also RDoc::Context#remove_from_documentation?
373
508
 
374
- ##
375
- # Finds the enclosure (namespace) for the given C +variable+.
509
+ def complete(min_visibility)
510
+ fix_basic_object_inheritance
376
511
 
377
- def find_c_enclosure(variable)
378
- @c_enclosure_classes.fetch variable do
379
- break unless name = @c_enclosure_names[variable]
512
+ # cache included modules before they are removed from the documentation
513
+ all_classes_and_modules.each { |cm| cm.ancestors }
380
514
 
381
- mod = find_class_or_module name
515
+ unless min_visibility == :nodoc
516
+ remove_nodoc @classes_hash
517
+ remove_nodoc @modules_hash
518
+ end
382
519
 
383
- unless mod then
384
- loaded_mod = load_class_data name
520
+ @unique_classes = find_unique @classes_hash
521
+ @unique_modules = find_unique @modules_hash
385
522
 
386
- file = loaded_mod.in_files.first
523
+ unique_classes_and_modules.each do |cm|
524
+ cm.complete min_visibility
525
+ end
387
526
 
388
- return unless file # legacy data source
527
+ @files_hash.each_key do |file_name|
528
+ tl = @files_hash[file_name]
389
529
 
390
- file.store = self
530
+ unless tl.text?
531
+ tl.modules_hash.clear
532
+ tl.classes_hash.clear
391
533
 
392
- mod = file.add_module RDoc::NormalModule, name
534
+ tl.classes_or_modules.each do |cm|
535
+ name = cm.full_name
536
+ if cm.type == 'class'
537
+ tl.classes_hash[name] = cm if @classes_hash[name]
538
+ else
539
+ tl.modules_hash[name] = cm if @modules_hash[name]
540
+ end
541
+ end
542
+ end
393
543
  end
544
+ end
394
545
 
395
- @c_enclosure_classes[variable] = mod
546
+ ##
547
+ # Hash of all files known to RDoc
548
+
549
+ def files_hash
550
+ @files_hash
396
551
  end
397
- end
398
552
 
399
- ##
400
- # Finds the class with +name+ in all discovered classes
553
+ ##
554
+ # Finds the enclosure (namespace) for the given C +variable+.
401
555
 
402
- def find_class_named(name)
403
- @classes_hash[name]
404
- end
556
+ def find_c_enclosure(variable)
557
+ @c_enclosure_classes.fetch variable do
558
+ break unless name = @c_enclosure_names[variable]
405
559
 
406
- ##
407
- # Finds the class with +name+ starting in namespace +from+
560
+ mod = find_class_or_module name
408
561
 
409
- def find_class_named_from(name, from)
410
- from = find_class_named from unless RDoc::Context === from
562
+ unless mod
563
+ loaded_mod = load_class_data name
411
564
 
412
- until RDoc::TopLevel === from do
413
- return nil unless from
565
+ file = loaded_mod.in_files.first
414
566
 
415
- klass = from.find_class_named name
416
- return klass if klass
567
+ return unless file # legacy data source
417
568
 
418
- from = from.parent
419
- end
569
+ file.store = self
420
570
 
421
- find_class_named name
422
- end
571
+ mod = file.add_module NormalModule, name
572
+ end
423
573
 
424
- ##
425
- # Finds the class or module with +name+
574
+ @c_enclosure_classes[variable] = mod
575
+ end
576
+ end
426
577
 
427
- def find_class_or_module(name)
428
- name = $' if name =~ /^::/
429
- @classes_hash[name] || @modules_hash[name]
430
- end
578
+ ##
579
+ # Finds the class with +name+ in all discovered classes
431
580
 
432
- ##
433
- # Finds the file with +name+ in all discovered files
581
+ def find_class_named(name)
582
+ @classes_hash[name]
583
+ end
434
584
 
435
- def find_file_named(name)
436
- @files_hash[name]
437
- end
585
+ ##
586
+ # Finds the class with +name+ starting in namespace +from+
438
587
 
439
- ##
440
- # Finds the module with +name+ in all discovered modules
588
+ def find_class_named_from(name, from)
589
+ from = find_class_named from unless Context === from
441
590
 
442
- def find_module_named(name)
443
- @modules_hash[name]
444
- end
591
+ until TopLevel === from do
592
+ return nil unless from
445
593
 
446
- ##
447
- # Returns the RDoc::TopLevel that is a text file and has the given
448
- # +file_name+
594
+ klass = from.find_class_named name
595
+ return klass if klass
596
+
597
+ from = from.parent
598
+ end
449
599
 
450
- def find_text_page(file_name)
451
- @text_files_hash.each_value.find do |file|
452
- file.full_name == file_name
600
+ find_class_named name
453
601
  end
454
- end
455
602
 
456
- ##
457
- # Finds unique classes/modules defined in +all_hash+,
458
- # and returns them as an array. Performs the alias
459
- # updates in +all_hash+: see ::complete.
460
- #--
461
- # TODO aliases should be registered by Context#add_module_alias
603
+ ##
604
+ # Finds the class or module with +name+
605
+
606
+ def find_class_or_module(name)
607
+ name = $' if name =~ /^::/
608
+ @classes_hash[name] || @modules_hash[name]
609
+ end
462
610
 
463
- def find_unique(all_hash)
464
- unique = []
611
+ ##
612
+ # Finds the file with +name+ in all discovered files
465
613
 
466
- all_hash.each_pair do |full_name, cm|
467
- unique << cm if full_name == cm.full_name
614
+ def find_file_named(name)
615
+ @files_hash[name]
468
616
  end
469
617
 
470
- unique
471
- end
618
+ ##
619
+ # Finds the module with +name+ in all discovered modules
472
620
 
473
- ##
474
- # Fixes the erroneous <tt>BasicObject < Object</tt> in 1.9.
475
- #
476
- # Because we assumed all classes without a stated superclass
477
- # inherit from Object, we have the above wrong inheritance.
478
- #
479
- # We fix BasicObject right away if we are running in a Ruby
480
- # version >= 1.9.
621
+ def find_module_named(name)
622
+ @modules_hash[name]
623
+ end
481
624
 
482
- def fix_basic_object_inheritance
483
- basic = classes_hash['BasicObject']
484
- return unless basic
485
- basic.superclass = nil
486
- end
625
+ ##
626
+ # Returns the RDoc::TopLevel that is a text file and has the given
627
+ # +file_name+
487
628
 
488
- ##
489
- # Friendly rendition of #path
490
-
491
- def friendly_path
492
- case type
493
- when :gem then
494
- parent = File.expand_path '..', @path
495
- "gem #{File.basename parent}"
496
- when :home then RDoc.home
497
- when :site then 'ruby site'
498
- when :system then 'ruby core'
499
- else @path
629
+ def find_text_page(file_name)
630
+ page = @files_hash[file_name]
631
+ page if page&.text?
500
632
  end
501
- end
502
633
 
503
- def inspect # :nodoc:
504
- "#<%s:0x%x %s %p>" % [self.class, object_id, @path, module_names.sort]
505
- end
634
+ ##
635
+ # Finds unique classes/modules defined in +all_hash+,
636
+ # and returns them as an array. Performs the alias
637
+ # updates in +all_hash+: see ::complete.
638
+ #--
639
+ # TODO aliases should be registered by Context#add_module_alias
506
640
 
507
- ##
508
- # Instance methods cache accessor. Maps a class to an Array of its
509
- # instance methods (not full name).
641
+ def find_unique(all_hash)
642
+ unique = []
510
643
 
511
- def instance_methods
512
- @cache[:instance_methods]
513
- end
644
+ all_hash.each_pair do |full_name, cm|
645
+ unique << cm if full_name == cm.full_name
646
+ end
514
647
 
515
- ##
516
- # Loads all items from this store into memory. This recreates a
517
- # documentation tree for use by a generator
648
+ unique
649
+ end
518
650
 
519
- def load_all
520
- load_cache
651
+ ##
652
+ # Fixes the erroneous <tt>BasicObject < Object</tt> in 1.9.
653
+ #
654
+ # Because we assumed all classes without a stated superclass
655
+ # inherit from Object, we have the above wrong inheritance.
656
+ #
657
+ # We fix BasicObject right away if we are running in a Ruby
658
+ # version >= 1.9.
521
659
 
522
- module_names.each do |module_name|
523
- mod = find_class_or_module(module_name) || load_class(module_name)
660
+ def fix_basic_object_inheritance
661
+ basic = classes_hash['BasicObject']
662
+ return unless basic
663
+ basic.superclass = nil
664
+ end
524
665
 
525
- # load method documentation since the loaded class/module does not have
526
- # it
527
- loaded_methods = mod.method_list.map do |method|
528
- load_method module_name, method.full_name
666
+ ##
667
+ # Friendly rendition of #path
668
+
669
+ def friendly_path
670
+ case type
671
+ when :gem
672
+ parent = File.expand_path '..', @path
673
+ "gem #{File.basename parent}"
674
+ when :home then ::RDoc.home
675
+ when :site then 'ruby site'
676
+ when :system then 'ruby core'
677
+ else @path
529
678
  end
679
+ end
530
680
 
531
- mod.method_list.replace loaded_methods
681
+ def inspect # :nodoc:
682
+ "#<%s:0x%x %s %p>" % [self.class, object_id, @path, module_names.sort]
683
+ end
532
684
 
533
- loaded_attributes = mod.attributes.map do |attribute|
534
- load_method module_name, attribute.full_name
535
- end
685
+ ##
686
+ # Instance methods cache accessor. Maps a class to an Array of its
687
+ # instance methods (not full name).
536
688
 
537
- mod.attributes.replace loaded_attributes
689
+ def instance_methods
690
+ @cache[:instance_methods]
538
691
  end
539
692
 
540
- all_classes_and_modules.each do |mod|
541
- descendent_re = /^#{mod.full_name}::[^:]+$/
693
+ ##
694
+ # Loads all items from this store into memory. This recreates a
695
+ # documentation tree for use by a generator
696
+
697
+ def load_all
698
+ load_cache
542
699
 
543
- module_names.each do |name|
544
- next unless name =~ descendent_re
700
+ module_names.each do |module_name|
701
+ mod = find_class_or_module(module_name) || load_class(module_name)
545
702
 
546
- descendent = find_class_or_module name
703
+ # load method documentation since the loaded class/module does not have
704
+ # it
705
+ loaded_methods = mod.method_list.map do |method|
706
+ load_method module_name, method.full_name
707
+ end
708
+
709
+ mod.method_list.replace loaded_methods
547
710
 
548
- case descendent
549
- when RDoc::NormalClass then
550
- mod.classes_hash[name] = descendent
551
- when RDoc::NormalModule then
552
- mod.modules_hash[name] = descendent
711
+ loaded_attributes = mod.attributes.map do |attribute|
712
+ load_method module_name, attribute.full_name
553
713
  end
714
+
715
+ mod.attributes.replace loaded_attributes
554
716
  end
555
- end
556
717
 
557
- @cache[:pages].each do |page_name|
558
- page = load_page page_name
559
- @files_hash[page_name] = page
560
- @text_files_hash[page_name] = page if page.text?
718
+ all_classes_and_modules.each do |mod|
719
+ descendent_re = /^#{mod.full_name}::[^:]+$/
720
+
721
+ module_names.each do |name|
722
+ next unless name =~ descendent_re
723
+
724
+ descendent = find_class_or_module name
725
+
726
+ case descendent
727
+ when NormalClass
728
+ mod.classes_hash[name] = descendent
729
+ when NormalModule
730
+ mod.modules_hash[name] = descendent
731
+ end
732
+ end
733
+ end
734
+
735
+ @page_index = nil
736
+ @cache[:pages].each do |page_name|
737
+ @files_hash[page_name] = load_page(page_name)
738
+ end
561
739
  end
562
- end
563
740
 
564
- ##
565
- # Loads cache file for this store
741
+ ##
742
+ # Loads cache file for this store
566
743
 
567
- def load_cache
568
- #orig_enc = @encoding
744
+ def load_cache
745
+ #orig_enc = @encoding
569
746
 
570
- @cache = marshal_load(cache_path)
747
+ @cache = marshal_load(cache_path)
571
748
 
572
- load_enc = @cache[:encoding]
749
+ load_enc = @cache[:encoding]
573
750
 
574
- # TODO this feature will be time-consuming to add:
575
- # a) Encodings may be incompatible but transcodeable
576
- # b) Need to warn in the appropriate spots, wherever they may be
577
- # c) Need to handle cross-cache differences in encodings
578
- # d) Need to warn when generating into a cache with different encodings
579
- #
580
- #if orig_enc and load_enc != orig_enc then
581
- # warn "Cached encoding #{load_enc} is incompatible with #{orig_enc}\n" \
582
- # "from #{path}/cache.ri" unless
583
- # Encoding.compatible? orig_enc, load_enc
584
- #end
751
+ # TODO this feature will be time-consuming to add:
752
+ # a) Encodings may be incompatible but transcodeable
753
+ # b) Need to warn in the appropriate spots, wherever they may be
754
+ # c) Need to handle cross-cache differences in encodings
755
+ # d) Need to warn when generating into a cache with different encodings
756
+ #
757
+ #if orig_enc and load_enc != orig_enc then
758
+ # warn "Cached encoding #{load_enc} is incompatible with #{orig_enc}\n" \
759
+ # "from #{path}/cache.ri" unless
760
+ # Encoding.compatible? orig_enc, load_enc
761
+ #end
585
762
 
586
- @encoding = load_enc unless @encoding
763
+ @encoding = load_enc unless @encoding
587
764
 
588
- @cache[:pages] ||= []
589
- @cache[:main] ||= nil
590
- @cache[:c_class_variables] ||= {}
591
- @cache[:c_singleton_class_variables] ||= {}
765
+ @cache[:pages] ||= []
766
+ @cache[:main] ||= nil
767
+ @cache[:c_class_variables] ||= {}
768
+ @cache[:c_singleton_class_variables] ||= {}
592
769
 
593
- @cache[:c_class_variables].each do |_, map|
594
- map.each do |variable, name|
595
- @c_enclosure_names[variable] = name
770
+ @cache[:c_class_variables].each do |_, map|
771
+ map.each do |variable, name|
772
+ @c_enclosure_names[variable] = name
773
+ end
596
774
  end
597
- end
598
775
 
599
- @cache
600
- rescue Errno::ENOENT
601
- end
776
+ @cache
777
+ rescue Errno::ENOENT
778
+ end
602
779
 
603
- ##
604
- # Loads ri data for +klass_name+ and hooks it up to this store.
780
+ ##
781
+ # Loads ri data for +klass_name+ and hooks it up to this store.
605
782
 
606
- def load_class(klass_name)
607
- obj = load_class_data klass_name
783
+ def load_class(klass_name)
784
+ obj = load_class_data klass_name
608
785
 
609
- obj.store = self
786
+ obj.store = self
610
787
 
611
- case obj
612
- when RDoc::NormalClass then
613
- @classes_hash[klass_name] = obj
614
- when RDoc::SingleClass then
615
- @classes_hash[klass_name] = obj
616
- when RDoc::NormalModule then
617
- @modules_hash[klass_name] = obj
788
+ case obj
789
+ when NormalClass
790
+ @classes_hash[klass_name] = obj
791
+ when SingleClass
792
+ @classes_hash[klass_name] = obj
793
+ when NormalModule
794
+ @modules_hash[klass_name] = obj
795
+ end
618
796
  end
619
- end
620
797
 
621
- ##
622
- # Loads ri data for +klass_name+
798
+ ##
799
+ # Loads ri data for +klass_name+
623
800
 
624
- def load_class_data(klass_name)
625
- file = class_file klass_name
801
+ def load_class_data(klass_name)
802
+ file = class_file klass_name
626
803
 
627
- marshal_load(file)
628
- rescue Errno::ENOENT => e
629
- error = MissingFileError.new(self, file, klass_name)
630
- error.set_backtrace e.backtrace
631
- raise error
632
- end
804
+ marshal_load(file)
805
+ rescue Errno::ENOENT => e
806
+ error = MissingFileError.new(self, file, klass_name)
807
+ error.set_backtrace e.backtrace
808
+ raise error
809
+ end
633
810
 
634
- ##
635
- # Loads ri data for +method_name+ in +klass_name+
636
-
637
- def load_method(klass_name, method_name)
638
- file = method_file klass_name, method_name
639
-
640
- obj = marshal_load(file)
641
- obj.store = self
642
- obj.parent ||= find_class_or_module(klass_name) || load_class(klass_name)
643
- obj
644
- rescue Errno::ENOENT => e
645
- error = MissingFileError.new(self, file, klass_name + method_name)
646
- error.set_backtrace e.backtrace
647
- raise error
648
- end
811
+ ##
812
+ # Loads ri data for +method_name+ in +klass_name+
813
+
814
+ def load_method(klass_name, method_name)
815
+ file = method_file klass_name, method_name
816
+
817
+ obj = marshal_load(file)
818
+ obj.store = self
819
+ obj.parent ||= find_class_or_module(klass_name) || load_class(klass_name)
820
+ obj
821
+ rescue Errno::ENOENT => e
822
+ error = MissingFileError.new(self, file, klass_name + method_name)
823
+ error.set_backtrace e.backtrace
824
+ raise error
825
+ end
649
826
 
650
- ##
651
- # Loads ri data for +page_name+
652
-
653
- def load_page(page_name)
654
- file = page_file page_name
655
-
656
- obj = marshal_load(file)
657
- obj.store = self
658
- obj
659
- rescue Errno::ENOENT => e
660
- error = MissingFileError.new(self, file, page_name)
661
- error.set_backtrace e.backtrace
662
- raise error
663
- end
827
+ ##
828
+ # Loads ri data for +page_name+
829
+
830
+ def load_page(page_name)
831
+ file = page_file page_name
832
+
833
+ obj = marshal_load(file)
834
+ obj.store = self
835
+ obj
836
+ rescue Errno::ENOENT => e
837
+ error = MissingFileError.new(self, file, page_name)
838
+ error.set_backtrace e.backtrace
839
+ raise error
840
+ end
664
841
 
665
- ##
666
- # Gets the main page for this RDoc store. This page is used as the root of
667
- # the RDoc server.
842
+ ##
843
+ # Gets the main page for this RDoc store. This page is used as the root of
844
+ # the RDoc server.
668
845
 
669
- def main
670
- @cache[:main]
671
- end
846
+ def main
847
+ @cache[:main]
848
+ end
672
849
 
673
- ##
674
- # Sets the main page for this RDoc store.
850
+ ##
851
+ # Sets the main page for this RDoc store.
675
852
 
676
- def main=(page)
677
- @cache[:main] = page
678
- end
853
+ def main=(page)
854
+ @cache[:main] = page
855
+ end
679
856
 
680
- ##
681
- # Converts the variable => ClassModule map +variables+ from a C parser into
682
- # a variable => class name map.
857
+ ##
858
+ # Converts the variable => ClassModule map +variables+ from a C parser into
859
+ # a variable => class name map.
683
860
 
684
- def make_variable_map(variables)
685
- map = {}
861
+ def make_variable_map(variables)
862
+ map = {}
686
863
 
687
- variables.each { |variable, class_module|
688
- map[variable] = class_module.full_name
689
- }
864
+ variables.each { |variable, class_module|
865
+ map[variable] = class_module.full_name
866
+ }
690
867
 
691
- map
692
- end
868
+ map
869
+ end
693
870
 
694
- ##
695
- # Path to the ri data for +method_name+ in +klass_name+
871
+ ##
872
+ # Path to the ri data for +method_name+ in +klass_name+
696
873
 
697
- def method_file(klass_name, method_name)
698
- method_name = method_name.split('::').last
699
- method_name =~ /#(.*)/
700
- method_type = $1 ? 'i' : 'c'
701
- method_name = $1 if $1
702
- method_name = method_name.gsub(/\W/) { "%%%02x" % $&[0].ord }
874
+ def method_file(klass_name, method_name)
875
+ method_name = method_name.split('::').last
876
+ method_name =~ /#(.*)/
877
+ method_type = $1 ? 'i' : 'c'
878
+ method_name = $1 if $1
879
+ method_name = method_name.gsub(/\W/) { "%%%02x" % $&[0].ord }
703
880
 
704
- File.join class_path(klass_name), "#{method_name}-#{method_type}.ri"
705
- end
881
+ File.join class_path(klass_name), "#{method_name}-#{method_type}.ri"
882
+ end
706
883
 
707
- ##
708
- # Modules cache accessor. An Array of all the module (and class) names in
709
- # the store.
884
+ ##
885
+ # Modules cache accessor. An Array of all the module (and class) names in
886
+ # the store.
710
887
 
711
- def module_names
712
- @cache[:modules]
713
- end
888
+ def module_names
889
+ @cache[:modules]
890
+ end
714
891
 
715
- ##
716
- # Hash of all modules known to RDoc
892
+ ##
893
+ # Hash of all modules known to RDoc
717
894
 
718
- def modules_hash
719
- @modules_hash
720
- end
895
+ def modules_hash
896
+ @modules_hash
897
+ end
721
898
 
722
- ##
723
- # Returns the RDoc::TopLevel that is a file and has the given +name+
899
+ ##
900
+ # Returns the RDoc::TopLevel that is a file and has the given +name+
901
+
902
+ def page(name)
903
+ @page_index ||= @files_hash.each_value.each_with_object({}) do |file, index|
904
+ index[file.page_name] ||= file
905
+ index[file.base_name] ||= file
906
+ end
724
907
 
725
- def page(name)
726
- @files_hash.each_value.find do |file|
727
- file.page_name == name or file.base_name == name
908
+ @page_index[name]
728
909
  end
729
- end
730
910
 
731
- ##
732
- # Path to the ri data for +page_name+
911
+ ##
912
+ # Path to the ri data for +page_name+
733
913
 
734
- def page_file(page_name)
735
- file_name = File.basename(page_name).gsub('.', '_')
914
+ def page_file(page_name)
915
+ file_name = File.basename(page_name).gsub('.', '_')
736
916
 
737
- File.join @path, File.dirname(page_name), "page-#{file_name}.ri"
738
- end
917
+ File.join @path, File.dirname(page_name), "page-#{file_name}.ri"
918
+ end
739
919
 
740
- ##
741
- # Removes from +all_hash+ the contexts that are nodoc or have no content.
742
- #
743
- # See RDoc::Context#remove_from_documentation?
920
+ ##
921
+ # Removes from +all_hash+ the contexts that are nodoc or have no content.
922
+ #
923
+ # See RDoc::Context#remove_from_documentation?
744
924
 
745
- def remove_nodoc(all_hash)
746
- all_hash.keys.each do |name|
747
- context = all_hash[name]
748
- all_hash.delete(name) if context.remove_from_documentation?
925
+ def remove_nodoc(all_hash)
926
+ all_hash.keys.each do |name|
927
+ context = all_hash[name]
928
+ all_hash.delete(name) if context.remove_from_documentation?
929
+ end
749
930
  end
750
- end
751
931
 
752
- ##
753
- # Saves all entries in the store
932
+ ##
933
+ # Saves all entries in the store
934
+
935
+ def save
936
+ load_cache
754
937
 
755
- def save
756
- load_cache
938
+ all_classes_and_modules.each do |klass|
939
+ save_class klass
757
940
 
758
- all_classes_and_modules.each do |klass|
759
- save_class klass
941
+ klass.each_method do |method|
942
+ save_method klass, method
943
+ end
760
944
 
761
- klass.each_method do |method|
762
- save_method klass, method
945
+ klass.attributes.each do |attribute|
946
+ save_method klass, attribute
947
+ end
763
948
  end
764
949
 
765
- klass.attributes.each do |attribute|
766
- save_method klass, attribute
950
+ all_files.each do |file|
951
+ save_page file
767
952
  end
768
- end
769
953
 
770
- all_files.each do |file|
771
- save_page file
954
+ save_cache
772
955
  end
773
956
 
774
- save_cache
775
- end
776
-
777
- ##
778
- # Writes the cache file for this store
957
+ ##
958
+ # Writes the cache file for this store
779
959
 
780
- def save_cache
781
- clean_cache_collection @cache[:ancestors]
782
- clean_cache_collection @cache[:attributes]
783
- clean_cache_collection @cache[:class_methods]
784
- clean_cache_collection @cache[:instance_methods]
960
+ def save_cache
961
+ clean_cache_collection @cache[:ancestors]
962
+ clean_cache_collection @cache[:attributes]
963
+ clean_cache_collection @cache[:class_methods]
964
+ clean_cache_collection @cache[:instance_methods]
785
965
 
786
- @cache[:modules].uniq!
787
- @cache[:modules].sort!
966
+ @cache[:modules].uniq!
967
+ @cache[:modules].sort!
788
968
 
789
- @cache[:pages].uniq!
790
- @cache[:pages].sort!
969
+ @cache[:pages].uniq!
970
+ @cache[:pages].sort!
791
971
 
792
- @cache[:encoding] = @encoding # this gets set twice due to assert_cache
972
+ @cache[:encoding] = @encoding # this gets set twice due to assert_cache
793
973
 
794
- @cache[:c_class_variables].merge! @c_class_variables
795
- @cache[:c_singleton_class_variables].merge! @c_singleton_class_variables
974
+ @cache[:c_class_variables].merge! @c_class_variables
975
+ @cache[:c_singleton_class_variables].merge! @c_singleton_class_variables
796
976
 
797
- return if @dry_run
977
+ return if @dry_run
798
978
 
799
- File.open cache_path, 'wb' do |io|
800
- Marshal.dump @cache, io
979
+ File.open cache_path, 'wb' do |io|
980
+ Marshal.dump @cache, io
981
+ end
801
982
  end
802
- end
803
983
 
804
- ##
805
- # Writes the ri data for +klass+ (or module)
984
+ ##
985
+ # Writes the ri data for +klass+ (or module)
806
986
 
807
- def save_class(klass)
808
- full_name = klass.full_name
987
+ def save_class(klass)
988
+ full_name = klass.full_name
809
989
 
810
- FileUtils.mkdir_p class_path(full_name) unless @dry_run
990
+ FileUtils.mkdir_p class_path(full_name) unless @dry_run
811
991
 
812
- @cache[:modules] << full_name
992
+ @cache[:modules] << full_name
813
993
 
814
- path = class_file full_name
994
+ path = class_file full_name
815
995
 
816
- begin
817
- disk_klass = load_class full_name
996
+ begin
997
+ disk_klass = load_class full_name
818
998
 
819
- klass = disk_klass.merge klass
820
- rescue MissingFileError
821
- end
999
+ klass = disk_klass.merge klass
1000
+ rescue MissingFileError
1001
+ end
822
1002
 
823
- # BasicObject has no ancestors
824
- ancestors = klass.direct_ancestors.compact.map do |ancestor|
825
- # HACK for classes we don't know about (class X < RuntimeError)
826
- String === ancestor ? ancestor : ancestor.full_name
827
- end
1003
+ # BasicObject has no ancestors
1004
+ ancestors = klass.direct_ancestors.compact.map do |ancestor|
1005
+ # HACK for classes we don't know about (class X < RuntimeError)
1006
+ String === ancestor ? ancestor : ancestor.full_name
1007
+ end
828
1008
 
829
- @cache[:ancestors][full_name] ||= []
830
- @cache[:ancestors][full_name].concat ancestors
1009
+ @cache[:ancestors][full_name] ||= []
1010
+ @cache[:ancestors][full_name].concat ancestors
831
1011
 
832
- attribute_definitions = klass.attributes.map do |attribute|
833
- "#{attribute.definition} #{attribute.name}"
834
- end
1012
+ attribute_definitions = klass.attributes.map do |attribute|
1013
+ "#{attribute.definition} #{attribute.name}"
1014
+ end
835
1015
 
836
- unless attribute_definitions.empty? then
837
- @cache[:attributes][full_name] ||= []
838
- @cache[:attributes][full_name].concat attribute_definitions
839
- end
1016
+ unless attribute_definitions.empty?
1017
+ @cache[:attributes][full_name] ||= []
1018
+ @cache[:attributes][full_name].concat attribute_definitions
1019
+ end
840
1020
 
841
- to_delete = []
1021
+ to_delete = []
842
1022
 
843
- unless klass.method_list.empty? then
844
- @cache[:class_methods][full_name] ||= []
845
- @cache[:instance_methods][full_name] ||= []
1023
+ unless klass.method_list.empty?
1024
+ @cache[:class_methods][full_name] ||= []
1025
+ @cache[:instance_methods][full_name] ||= []
846
1026
 
847
- class_methods, instance_methods =
848
- klass.method_list.partition { |meth| meth.singleton }
1027
+ class_methods, instance_methods =
1028
+ klass.method_list.partition { |meth| meth.singleton }
849
1029
 
850
- class_methods = class_methods. map { |method| method.name }
851
- instance_methods = instance_methods.map { |method| method.name }
852
- attribute_names = klass.attributes.map { |attr| attr.name }
1030
+ class_methods = class_methods. map { |method| method.name }
1031
+ instance_methods = instance_methods.map { |method| method.name }
1032
+ attribute_names = klass.attributes.map { |attr| attr.name }
853
1033
 
854
- old = @cache[:class_methods][full_name] - class_methods
855
- to_delete.concat old.map { |method|
856
- method_file full_name, "#{full_name}::#{method}"
857
- }
1034
+ old = @cache[:class_methods][full_name] - class_methods
1035
+ to_delete.concat old.map { |method|
1036
+ method_file full_name, "#{full_name}::#{method}"
1037
+ }
858
1038
 
859
- old = @cache[:instance_methods][full_name] -
860
- instance_methods - attribute_names
861
- to_delete.concat old.map { |method|
862
- method_file full_name, "#{full_name}##{method}"
863
- }
1039
+ old = @cache[:instance_methods][full_name] -
1040
+ instance_methods - attribute_names
1041
+ to_delete.concat old.map { |method|
1042
+ method_file full_name, "#{full_name}##{method}"
1043
+ }
864
1044
 
865
- @cache[:class_methods][full_name] = class_methods
866
- @cache[:instance_methods][full_name] = instance_methods
867
- end
1045
+ @cache[:class_methods][full_name] = class_methods
1046
+ @cache[:instance_methods][full_name] = instance_methods
1047
+ end
868
1048
 
869
- return if @dry_run
1049
+ return if @dry_run
870
1050
 
871
- FileUtils.rm_f to_delete
1051
+ FileUtils.rm_f to_delete
872
1052
 
873
- File.open path, 'wb' do |io|
874
- Marshal.dump klass, io
1053
+ File.open path, 'wb' do |io|
1054
+ Marshal.dump klass, io
1055
+ end
875
1056
  end
876
- end
877
1057
 
878
- ##
879
- # Writes the ri data for +method+ on +klass+
1058
+ ##
1059
+ # Writes the ri data for +method+ on +klass+
880
1060
 
881
- def save_method(klass, method)
882
- full_name = klass.full_name
1061
+ def save_method(klass, method)
1062
+ full_name = klass.full_name
883
1063
 
884
- FileUtils.mkdir_p class_path(full_name) unless @dry_run
1064
+ FileUtils.mkdir_p class_path(full_name) unless @dry_run
885
1065
 
886
- cache = if method.singleton then
887
- @cache[:class_methods]
888
- else
889
- @cache[:instance_methods]
890
- end
891
- cache[full_name] ||= []
892
- cache[full_name] << method.name
1066
+ cache = if method.singleton
1067
+ @cache[:class_methods]
1068
+ else
1069
+ @cache[:instance_methods]
1070
+ end
1071
+ cache[full_name] ||= []
1072
+ cache[full_name] << method.name
893
1073
 
894
- return if @dry_run
1074
+ return if @dry_run
895
1075
 
896
- File.open method_file(full_name, method.full_name), 'wb' do |io|
897
- Marshal.dump method, io
1076
+ File.open method_file(full_name, method.full_name), 'wb' do |io|
1077
+ Marshal.dump method, io
1078
+ end
898
1079
  end
899
- end
900
1080
 
901
- ##
902
- # Writes the ri data for +page+
1081
+ ##
1082
+ # Writes the ri data for +page+
903
1083
 
904
- def save_page(page)
905
- return unless page.text?
1084
+ def save_page(page)
1085
+ return unless page.text?
906
1086
 
907
- path = page_file page.full_name
1087
+ path = page_file page.full_name
908
1088
 
909
- FileUtils.mkdir_p File.dirname(path) unless @dry_run
1089
+ FileUtils.mkdir_p File.dirname(path) unless @dry_run
910
1090
 
911
- cache[:pages] ||= []
912
- cache[:pages] << page.full_name
1091
+ cache[:pages] ||= []
1092
+ cache[:pages] << page.full_name
913
1093
 
914
- return if @dry_run
1094
+ return if @dry_run
915
1095
 
916
- File.open path, 'wb' do |io|
917
- Marshal.dump page, io
1096
+ File.open path, 'wb' do |io|
1097
+ Marshal.dump page, io
1098
+ end
918
1099
  end
919
- end
920
1100
 
921
- ##
922
- # Source of the contents of this store.
923
- #
924
- # For a store from a gem the source is the gem name. For a store from the
925
- # home directory the source is "home". For system ri store (the standard
926
- # library documentation) the source is"ruby". For a store from the site
927
- # ri directory the store is "site". For other stores the source is the
928
- # #path.
929
-
930
- def source
931
- case type
932
- when :gem then File.basename File.expand_path '..', @path
933
- when :home then 'home'
934
- when :site then 'site'
935
- when :system then 'ruby'
936
- else @path
1101
+ ##
1102
+ # Source of the contents of this store.
1103
+ #
1104
+ # For a store from a gem the source is the gem name. For a store from the
1105
+ # home directory the source is "home". For system ri store (the standard
1106
+ # library documentation) the source is"ruby". For a store from the site
1107
+ # ri directory the store is "site". For other stores the source is the
1108
+ # #path.
1109
+
1110
+ def source
1111
+ case type
1112
+ when :gem then File.basename File.expand_path '..', @path
1113
+ when :home then 'home'
1114
+ when :site then 'site'
1115
+ when :system then 'ruby'
1116
+ else @path
1117
+ end
937
1118
  end
938
- end
939
1119
 
940
- ##
941
- # Gets the title for this RDoc store. This is used as the title in each
942
- # page on the RDoc server
1120
+ ##
1121
+ # Gets the title for this RDoc store. This is used as the title in each
1122
+ # page on the RDoc server
943
1123
 
944
- def title
945
- @cache[:title]
946
- end
1124
+ def title
1125
+ @cache[:title]
1126
+ end
947
1127
 
948
- ##
949
- # Sets the title page for this RDoc store.
1128
+ ##
1129
+ # Sets the title page for this RDoc store.
950
1130
 
951
- def title=(title)
952
- @cache[:title] = title
953
- end
1131
+ def title=(title)
1132
+ @cache[:title] = title
1133
+ end
954
1134
 
955
- ##
956
- # Returns the unique classes discovered by RDoc.
957
- #
958
- # ::complete must have been called prior to using this method.
1135
+ ##
1136
+ # Returns the unique classes discovered by RDoc.
1137
+ #
1138
+ # ::complete must have been called prior to using this method.
959
1139
 
960
- def unique_classes
961
- @unique_classes
962
- end
1140
+ def unique_classes
1141
+ @unique_classes
1142
+ end
963
1143
 
964
- ##
965
- # Returns the unique classes and modules discovered by RDoc.
966
- # ::complete must have been called prior to using this method.
1144
+ ##
1145
+ # Returns the unique classes and modules discovered by RDoc.
1146
+ # ::complete must have been called prior to using this method.
967
1147
 
968
- def unique_classes_and_modules
969
- @unique_classes + @unique_modules
970
- end
1148
+ def unique_classes_and_modules
1149
+ @unique_classes + @unique_modules
1150
+ end
971
1151
 
972
- ##
973
- # Returns the unique modules discovered by RDoc.
974
- # ::complete must have been called prior to using this method.
1152
+ ##
1153
+ # Returns the unique modules discovered by RDoc.
1154
+ # ::complete must have been called prior to using this method.
975
1155
 
976
- def unique_modules
977
- @unique_modules
978
- end
1156
+ def unique_modules
1157
+ @unique_modules
1158
+ end
979
1159
 
980
1160
  private
981
- def marshal_load(file)
982
- File.open(file, 'rb') {|io| Marshal.load(io, MarshalFilter)}
983
- end
984
1161
 
985
- MarshalFilter = proc do |obj|
986
- case obj
987
- when true, false, nil, Array, Class, Encoding, Hash, Integer, String, Symbol, RDoc::Text
988
- else
989
- unless obj.class.name.start_with?("RDoc::")
990
- raise TypeError, "not permitted class: #{obj.class.name}"
1162
+ def remove_classes_and_modules(cms)
1163
+ cms.each do |cm|
1164
+ remove_classes_and_modules(cm.classes_and_modules)
1165
+
1166
+ if cm.is_a?(NormalModule)
1167
+ @modules_hash.delete(cm.full_name)
1168
+ else
1169
+ @classes_hash.delete(cm.full_name)
1170
+ end
991
1171
  end
992
1172
  end
993
- obj
994
- end
995
- private_constant :MarshalFilter
996
1173
 
1174
+ def marshal_load(file)
1175
+ File.open(file, 'rb') {|io| Marshal.load(io, MarshalFilter)}
1176
+ end
1177
+
1178
+ MarshalFilter = proc do |obj|
1179
+ case obj
1180
+ when true, false, nil, Array, Class, ::Encoding, Hash, Integer, String, Symbol, Text
1181
+ else
1182
+ unless obj.class.name.start_with?("RDoc::")
1183
+ raise TypeError, "not permitted class: #{obj.class.name}"
1184
+ end
1185
+ end
1186
+ obj
1187
+ end
1188
+ private_constant :MarshalFilter
1189
+
1190
+ end
997
1191
  end