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
@@ -1,939 +1,975 @@
1
1
  # frozen_string_literal: true
2
- ##
3
- # ClassModule is the base class for objects representing either a class or a
4
- # module.
5
-
6
- class RDoc::ClassModule < RDoc::Context
7
-
8
- ##
9
- # 1::
10
- # RDoc 3.7
11
- # * Added visibility, singleton and file to attributes
12
- # * Added file to constants
13
- # * Added file to includes
14
- # * Added file to methods
15
- # 2::
16
- # RDoc 3.13
17
- # * Added extends
18
- # 3::
19
- # RDoc 4.0
20
- # * Added sections
21
- # * Added in_files
22
- # * Added parent name
23
- # * Complete Constant dump
24
-
25
- MARSHAL_VERSION = 3 # :nodoc:
26
-
27
- ##
28
- # Constants that are aliases for this class or module
2
+ module RDoc
3
+ ##
4
+ # ClassModule is the base class for objects representing either a class or a
5
+ # module.
6
+
7
+ class ClassModule < ::RDoc::Context
8
+
9
+ ##
10
+ # 1::
11
+ # RDoc 3.7
12
+ # * Added visibility, singleton and file to attributes
13
+ # * Added file to constants
14
+ # * Added file to includes
15
+ # * Added file to methods
16
+ # 2::
17
+ # RDoc 3.13
18
+ # * Added extends
19
+ # 3::
20
+ # RDoc 4.0
21
+ # * Added sections
22
+ # * Added in_files
23
+ # * Added parent name
24
+ # * Complete Constant dump
25
+
26
+ MARSHAL_VERSION = 3 # :nodoc:
27
+
28
+ ##
29
+ # Constants that are aliases for this class or module
30
+
31
+ attr_accessor :constant_aliases
32
+
33
+ ##
34
+ # A hash of <tt>{ location => [comments] }</tt> documenting this class/module.
35
+ # Use #add_comment to add comments.
36
+ #
37
+ # Ruby hashes maintain insertion order, so comments render in the order
38
+ # they were first added. Each location maps to an array of comments,
39
+ # allowing a class reopened in the same file to accumulate multiple comments.
40
+ #
41
+ # Before marshalling:
42
+ # - +location+ is an RDoc::TopLevel
43
+ # - +comments+ are Strings
44
+ #
45
+ # After unmarshalling:
46
+ # - +location+ is a filename String
47
+ # - +comments+ are RDoc::Markup::Documents
48
+
49
+ attr_accessor :comment_location
50
+
51
+ ##
52
+ # Class or module this constant is an alias for
53
+
54
+ attr_accessor :is_alias_for
55
+
56
+ ##
57
+ # Return a RDoc::ClassModule of class +class_type+ that is a copy
58
+ # of module +module+. Used to promote modules to classes.
59
+ #--
60
+ # TODO move to RDoc::NormalClass (I think)
61
+
62
+ def self.from_module(class_type, mod)
63
+ klass = class_type.new mod.name
64
+
65
+ mod.comment_location.each do |location, comments|
66
+ comments.each { |comment| klass.add_comment comment, location }
67
+ end
29
68
 
30
- attr_accessor :constant_aliases
69
+ klass.parent = mod.parent
70
+ klass.section = mod.section
71
+
72
+ klass.attributes.concat mod.attributes
73
+ klass.method_list.concat mod.method_list
74
+ klass.aliases.concat mod.aliases
75
+ klass.external_aliases.concat mod.external_aliases
76
+ klass.constants.concat mod.constants
77
+ klass.includes.concat mod.includes
78
+ klass.extends.concat mod.extends
79
+
80
+ klass.methods_hash.update mod.methods_hash
81
+ klass.constants_hash.update mod.constants_hash
82
+
83
+ klass.current_section = mod.current_section
84
+ klass.in_files.concat mod.in_files
85
+ klass.sections.concat mod.sections
86
+ klass.unmatched_alias_lists = mod.unmatched_alias_lists
87
+ klass.current_section = mod.current_section
88
+ klass.classes_hash.update mod.classes_hash
89
+ klass.modules_hash.update mod.modules_hash
90
+ klass.metadata.update mod.metadata
91
+
92
+ klass.document_self = mod.received_nodoc ? nil : mod.document_self
93
+ klass.document_children = mod.document_children
94
+ klass.force_documentation = mod.force_documentation
95
+ klass.done_documenting = mod.done_documenting
96
+
97
+ # update the parent of all children
98
+
99
+ (klass.attributes +
100
+ klass.method_list +
101
+ klass.aliases +
102
+ klass.external_aliases +
103
+ klass.constants +
104
+ klass.includes +
105
+ klass.extends +
106
+ klass.classes +
107
+ klass.modules).each do |obj|
108
+ obj.parent = klass
109
+ obj.full_name = nil
110
+ end
31
111
 
32
- ##
33
- # An array of `[comment, location]` pairs documenting this class/module.
34
- # Use #add_comment to add comments.
35
- #
36
- # Before marshalling:
37
- # - +comment+ is a String
38
- # - +location+ is an RDoc::TopLevel
39
- #
40
- # After unmarshalling:
41
- # - +comment+ is an RDoc::Markup::Document
42
- # - +location+ is a filename String
43
- #
44
- # These type changes are acceptable (for now) because:
45
- # - +comment+: Both String and Document respond to #empty?, and #parse
46
- # returns Document as-is (see RDoc::Text#parse)
47
- # - +location+: Only used by #parse to set Document#file, which accepts
48
- # both TopLevel (extracts relative_name) and String
49
-
50
- attr_accessor :comment_location
112
+ klass
113
+ end
51
114
 
52
- ##
53
- # Class or module this constant is an alias for
115
+ ##
116
+ # Creates a new ClassModule with +name+ with optional +superclass+
117
+ #
118
+ # This is a constructor for subclasses, and must never be called directly.
54
119
 
55
- attr_accessor :is_alias_for
120
+ def initialize(name, superclass = nil)
121
+ @constant_aliases = []
122
+ @is_alias_for = nil
123
+ @name = name
124
+ @superclass = superclass
125
+ @comment_location = {} # Hash of { location => [comments] }
56
126
 
57
- ##
58
- # Return a RDoc::ClassModule of class +class_type+ that is a copy
59
- # of module +module+. Used to promote modules to classes.
60
- #--
61
- # TODO move to RDoc::NormalClass (I think)
62
-
63
- def self.from_module(class_type, mod)
64
- klass = class_type.new mod.name
65
-
66
- mod.comment_location.each do |comment, location|
67
- klass.add_comment comment, location
68
- end
69
-
70
- klass.parent = mod.parent
71
- klass.section = mod.section
72
-
73
- klass.attributes.concat mod.attributes
74
- klass.method_list.concat mod.method_list
75
- klass.aliases.concat mod.aliases
76
- klass.external_aliases.concat mod.external_aliases
77
- klass.constants.concat mod.constants
78
- klass.includes.concat mod.includes
79
- klass.extends.concat mod.extends
80
-
81
- klass.methods_hash.update mod.methods_hash
82
- klass.constants_hash.update mod.constants_hash
83
-
84
- klass.current_section = mod.current_section
85
- klass.in_files.concat mod.in_files
86
- klass.sections.concat mod.sections
87
- klass.unmatched_alias_lists = mod.unmatched_alias_lists
88
- klass.current_section = mod.current_section
89
- klass.visibility = mod.visibility
90
-
91
- klass.classes_hash.update mod.classes_hash
92
- klass.modules_hash.update mod.modules_hash
93
- klass.metadata.update mod.metadata
94
-
95
- klass.document_self = mod.received_nodoc ? nil : mod.document_self
96
- klass.document_children = mod.document_children
97
- klass.force_documentation = mod.force_documentation
98
- klass.done_documenting = mod.done_documenting
99
-
100
- # update the parent of all children
101
-
102
- (klass.attributes +
103
- klass.method_list +
104
- klass.aliases +
105
- klass.external_aliases +
106
- klass.constants +
107
- klass.includes +
108
- klass.extends +
109
- klass.classes +
110
- klass.modules).each do |obj|
111
- obj.parent = klass
112
- obj.full_name = nil
113
- end
114
-
115
- klass
116
- end
127
+ super()
128
+ end
117
129
 
118
- ##
119
- # Creates a new ClassModule with +name+ with optional +superclass+
120
- #
121
- # This is a constructor for subclasses, and must never be called directly.
122
-
123
- def initialize(name, superclass = nil)
124
- @constant_aliases = []
125
- @is_alias_for = nil
126
- @name = name
127
- @superclass = superclass
128
- @comment_location = [] # Array of [comment, location] pairs
129
-
130
- super()
131
- end
130
+ ##
131
+ # Adds +comment+ to this ClassModule's list of comments at +location+. This
132
+ # method is preferred over #comment= since it allows ri data to be updated
133
+ # across multiple runs.
132
134
 
133
- ##
134
- # Adds +comment+ to this ClassModule's list of comments at +location+. This
135
- # method is preferred over #comment= since it allows ri data to be updated
136
- # across multiple runs.
135
+ def add_comment(comment, location)
136
+ return unless document_self
137
137
 
138
- def add_comment(comment, location)
139
- return unless document_self
138
+ original = comment
140
139
 
141
- original = comment
140
+ comment = case comment
141
+ when Comment
142
+ comment.normalize
143
+ else
144
+ normalize_comment comment
145
+ end
142
146
 
143
- comment = case comment
144
- when RDoc::Comment then
145
- comment.normalize
146
- else
147
- normalize_comment comment
148
- end
147
+ (@comment_location[location] ||= []) << comment
149
148
 
150
- if location.parser == RDoc::Parser::C
151
- @comment_location.delete_if { |(_, l)| l == location }
149
+ self.comment = original
152
150
  end
153
151
 
154
- @comment_location << [comment, location]
155
-
156
- self.comment = original
157
- end
158
-
159
- def add_things(my_things, other_things) # :nodoc:
160
- other_things.each do |group, things|
161
- my_things[group].each { |thing| yield false, thing } if
162
- my_things.include? group
152
+ def add_things(my_things, other_things) # :nodoc:
153
+ other_things.each do |group, things|
154
+ my_things[group].each { |thing| yield false, thing } if
155
+ my_things.include? group
163
156
 
164
- things.each do |thing|
165
- yield true, thing
157
+ things.each do |thing|
158
+ yield true, thing
159
+ end
166
160
  end
167
161
  end
168
- end
169
-
170
- ##
171
- # Ancestors list for this ClassModule: the list of included modules
172
- # (classes will add their superclass if any).
173
- #
174
- # Returns the included classes or modules, not the includes
175
- # themselves. The returned values are either String or
176
- # RDoc::NormalModule instances (see RDoc::Include#module).
177
- #
178
- # The values are returned in reverse order of their inclusion,
179
- # which is the order suitable for searching methods/attributes
180
- # in the ancestors. The superclass, if any, comes last.
181
-
182
- def ancestors
183
- includes.map { |i| i.module }.reverse
184
- end
185
-
186
- def aref_prefix # :nodoc:
187
- raise NotImplementedError, "missing aref_prefix for #{self.class}"
188
- end
189
162
 
190
- ##
191
- # HTML fragment reference for this module or class using GitHub-style
192
- # anchor format (lowercase, :: replaced with -).
193
- #
194
- # Examples:
195
- # Foo -> class-foo
196
- # Foo::Bar -> class-foo-bar
197
-
198
- def aref
199
- "#{aref_prefix}-#{full_name.downcase.gsub('::', '-')}"
200
- end
163
+ ##
164
+ # Ancestors list for this ClassModule: the list of included modules
165
+ # (classes will add their superclass if any).
166
+ #
167
+ # Returns the included classes or modules, not the includes
168
+ # themselves. The returned values are either String or
169
+ # RDoc::NormalModule instances (see RDoc::Include#module).
170
+ #
171
+ # The values are returned in reverse order of their inclusion,
172
+ # which is the order suitable for searching methods/attributes
173
+ # in the ancestors. The superclass, if any, comes last.
201
174
 
202
- ##
203
- # Legacy HTML fragment reference for backward compatibility.
204
- # Returns the old RDoc-style anchor format.
205
- #
206
- # Examples:
207
- # Foo -> class-Foo
208
- # Foo::Bar -> class-Foo::Bar
209
-
210
- def legacy_aref
211
- "#{aref_prefix}-#{full_name}"
212
- end
213
-
214
- ##
215
- # Ancestors of this class or module only
175
+ def ancestors
176
+ included_ancestors
177
+ end
216
178
 
217
- alias direct_ancestors ancestors
179
+ def included_ancestors # :nodoc:
180
+ includes.map { |i| i.module }.reverse
181
+ end
218
182
 
219
- ##
220
- # Clears the comment. Used by the Ruby parser.
183
+ def aref_prefix # :nodoc:
184
+ raise NotImplementedError, "missing aref_prefix for #{self.class}"
185
+ end
221
186
 
222
- def clear_comment
223
- @comment = ''
224
- end
187
+ ##
188
+ # HTML fragment reference for this module or class using GitHub-style
189
+ # anchor format (lowercase, :: replaced with -).
190
+ #
191
+ # Examples:
192
+ # Foo -> class-foo
193
+ # Foo::Bar -> class-foo-bar
225
194
 
226
- ##
227
- # This method is deprecated, use #add_comment instead.
228
- #
229
- # Appends +comment+ to the current comment, but separated by a rule. Works
230
- # more like <tt>+=</tt>.
231
-
232
- def comment=(comment) # :nodoc:
233
- comment = case comment
234
- when RDoc::Comment then
235
- comment.normalize
236
- else
237
- normalize_comment comment
238
- end
195
+ def aref
196
+ "#{aref_prefix}-#{full_name.downcase.gsub('::', '-')}"
197
+ end
239
198
 
240
- comment = "#{@comment.to_s}\n---\n#{comment.to_s}" unless @comment.empty?
199
+ ##
200
+ # Legacy HTML fragment reference for backward compatibility.
201
+ # Returns the old RDoc-style anchor format.
202
+ #
203
+ # Examples:
204
+ # Foo -> class-Foo
205
+ # Foo::Bar -> class-Foo::Bar
241
206
 
242
- super comment
243
- end
207
+ def legacy_aref
208
+ "#{aref_prefix}-#{full_name}"
209
+ end
244
210
 
245
- ##
246
- # Prepares this ClassModule for use by a generator.
247
- #
248
- # See RDoc::Store#complete
249
-
250
- def complete(min_visibility)
251
- update_aliases
252
- remove_nodoc_children
253
- embed_mixins
254
- update_includes
255
- update_extends
256
- remove_invisible min_visibility
257
- end
211
+ ##
212
+ # Ancestors of this class or module only
258
213
 
259
- ##
260
- # Does this ClassModule or any of its methods have document_self set?
214
+ alias direct_ancestors ancestors
261
215
 
262
- def document_self_or_methods
263
- document_self || method_list.any?{ |m| m.document_self }
264
- end
216
+ ##
217
+ # Clears the comment. Used by the Ruby parser.
265
218
 
266
- ##
267
- # Does this class or module have a comment with content or is
268
- # #received_nodoc true?
219
+ def clear_comment
220
+ @comment = ''
221
+ end
269
222
 
270
- def documented?
271
- return true if @received_nodoc
272
- return false if @comment_location.empty?
273
- @comment_location.any? { |comment, _| not comment.empty? }
274
- end
223
+ ##
224
+ # This method is deprecated, use #add_comment instead.
225
+ #
226
+ # Appends +comment+ to the current comment, but separated by a rule. Works
227
+ # more like <tt>+=</tt>.
275
228
 
276
- ##
277
- # Iterates the ancestors of this class or module for which an
278
- # RDoc::ClassModule exists.
229
+ def comment=(comment) # :nodoc:
230
+ comment = case comment
231
+ when Comment
232
+ comment.normalize
233
+ else
234
+ normalize_comment comment
235
+ end
279
236
 
280
- def each_ancestor # :yields: module
281
- return enum_for __method__ unless block_given?
237
+ comment = "#{@comment.to_s}\n---\n#{comment.to_s}" unless @comment.empty?
282
238
 
283
- ancestors.each do |mod|
284
- next if String === mod
285
- next if self == mod
286
- yield mod
239
+ super comment
287
240
  end
288
- end
289
241
 
290
- ##
291
- # Looks for a symbol in the #ancestors. See Context#find_local_symbol.
242
+ ##
243
+ # Prepares this ClassModule for use by a generator.
244
+ #
245
+ # See RDoc::Store#complete
292
246
 
293
- def find_ancestor_local_symbol(symbol)
294
- each_ancestor do |m|
295
- res = m.find_local_symbol(symbol)
296
- return res if res
247
+ def complete(min_visibility)
248
+ update_aliases
249
+ remove_nodoc_children
250
+ embed_mixins
251
+ update_includes
252
+ update_extends
253
+ remove_invisible min_visibility
297
254
  end
298
255
 
299
- nil
300
- end
256
+ ##
257
+ # Does this ClassModule or any of its methods have document_self set?
301
258
 
302
- ##
303
- # Finds a class or module with +name+ in this namespace or its descendants
259
+ def document_self_or_methods
260
+ document_self || method_list.any?{ |m| m.document_self }
261
+ end
304
262
 
305
- def find_class_named(name)
306
- return self if full_name == name
307
- return self if @name == name
263
+ ##
264
+ # Does this class or module have a comment with content or is
265
+ # #received_nodoc true?
308
266
 
309
- @classes.values.find do |klass|
310
- next if klass == self
311
- klass.find_class_named name
267
+ def documented?
268
+ return true if @received_nodoc
269
+ return false if @comment_location.empty?
270
+ @comment_location.each_value.any? { |comments| comments.any? { |c| not c.empty? } }
312
271
  end
313
- end
314
272
 
315
- ##
316
- # Return the fully qualified name of this class or module
317
-
318
- def full_name
319
- @full_name ||= if RDoc::ClassModule === parent then
320
- "#{parent.full_name}::#{@name}"
321
- else
322
- @name
323
- end
324
- end
273
+ ##
274
+ # Iterates the ancestors of this class or module for which an
275
+ # RDoc::ClassModule exists.
325
276
 
326
- ##
327
- # Return array of full_name splitted by +::+.
277
+ def each_ancestor # :yields: module
278
+ return enum_for __method__ unless block_given?
328
279
 
329
- def nesting_namespaces
330
- @namespaces ||= full_name.split("::").reject(&:empty?)
331
- end
280
+ ancestors.each do |mod|
281
+ next if String === mod
282
+ next if self == mod
283
+ yield mod
284
+ end
285
+ end
332
286
 
333
- ##
334
- # Return array of fully qualified nesting namespaces.
335
- #
336
- # For example, if full_name is +A::B::C+, this method returns <code>["A", "A::B", "A::B::C"]</code>
287
+ ##
288
+ # Looks for a symbol in the #ancestors. See Context#find_local_symbol.
337
289
 
338
- def fully_qualified_nesting_namespaces
339
- return nesting_namespaces if nesting_namespaces.length < 2
340
- @fqns ||= nesting_namespaces.inject([]) do |list, n|
341
- list << (list.empty? ? n : "#{list.last}::#{n}")
290
+ def find_ancestor_local_symbol(symbol)
291
+ each_ancestor do |m|
292
+ res = m.find_local_symbol(symbol)
293
+ return res if res
294
+ end
295
+
296
+ nil
342
297
  end
343
- end
344
298
 
345
- ##
346
- # TODO: filter included items by #display?
299
+ ##
300
+ # Finds a class or module with +name+ in this namespace or its descendants
347
301
 
348
- def marshal_dump # :nodoc:
349
- attrs = attributes.sort.map do |attr|
350
- next unless attr.display?
351
- [ attr.name, attr.rw,
352
- attr.visibility, attr.singleton, attr.file_name,
353
- ]
354
- end.compact
355
-
356
- method_types = methods_by_type.map do |type, visibilities|
357
- visibilities = visibilities.map do |visibility, methods|
358
- method_names = methods.map do |method|
359
- next unless method.display?
360
- [method.name, method.file_name]
361
- end.compact
362
-
363
- [visibility, method_names.uniq]
364
- end
365
-
366
- [type, visibilities]
367
- end
368
-
369
- [ MARSHAL_VERSION,
370
- @name,
371
- full_name,
372
- @superclass,
373
- parse(@comment_location),
374
- attrs,
375
- constants.select { |constant| constant.display? },
376
- includes.map do |incl|
377
- next unless incl.display?
378
- [incl.name, parse(incl.comment), incl.file_name]
379
- end.compact,
380
- method_types,
381
- extends.map do |ext|
382
- next unless ext.display?
383
- [ext.name, parse(ext.comment), ext.file_name]
384
- end.compact,
385
- @sections.values,
386
- @in_files.map do |tl|
387
- tl.relative_name
388
- end,
389
- parent.full_name,
390
- parent.class,
391
- ]
392
- end
302
+ def find_class_named(name)
303
+ return self if full_name == name
304
+ return self if @name == name
393
305
 
394
- def marshal_load(array) # :nodoc:
395
- initialize_visibility
396
- initialize_methods_etc
397
- @current_section = nil
398
- @document_self = true
399
- @done_documenting = false
400
- @parent = nil
401
- @temporary_section = nil
402
- @visibility = nil
403
- @classes = {}
404
- @modules = {}
405
-
406
- @name = array[1]
407
- @full_name = array[2]
408
- @superclass = array[3]
409
- document = array[4]
410
-
411
- @comment = RDoc::Comment.from_document document
412
-
413
- @comment_location = if document.parts.first.is_a?(RDoc::Markup::Document)
414
- document.parts.map { |doc| [doc, doc.file] }
415
- else
416
- [[document, document.file]]
417
- end
418
-
419
- array[5].each do |name, rw, visibility, singleton, file|
420
- singleton ||= false
421
- visibility ||= :public
422
-
423
- attr = RDoc::Attr.new nil, name, rw, nil, singleton: singleton
424
-
425
- add_attribute attr
426
- attr.visibility = visibility
427
- attr.record_location RDoc::TopLevel.new file
428
- end
429
-
430
- array[6].each do |constant, document, file|
431
- case constant
432
- when RDoc::Constant then
433
- add_constant constant
434
- else
435
- constant = add_constant RDoc::Constant.new(constant, nil, RDoc::Comment.from_document(document))
436
- constant.record_location RDoc::TopLevel.new file
306
+ @classes.values.find do |klass|
307
+ next if klass == self
308
+ klass.find_class_named name
437
309
  end
438
310
  end
439
311
 
440
- array[7].each do |name, document, file|
441
- incl = add_include RDoc::Include.new(name, RDoc::Comment.from_document(document))
442
- incl.record_location RDoc::TopLevel.new file
312
+ ##
313
+ # Return the fully qualified name of this class or module
314
+
315
+ def full_name
316
+ @full_name ||= if ClassModule === parent
317
+ "#{parent.full_name}::#{@name}"
318
+ else
319
+ @name
320
+ end
443
321
  end
444
322
 
445
- array[8].each do |type, visibilities|
446
- visibilities.each do |visibility, methods|
447
- @visibility = visibility
323
+ ##
324
+ # Return array of full_name splitted by +::+.
448
325
 
449
- methods.each do |name, file|
450
- method = RDoc::AnyMethod.new nil, name, singleton: type == 'class'
451
- method.record_location RDoc::TopLevel.new file
452
- add_method method
453
- end
454
- end
326
+ def nesting_namespaces
327
+ @namespaces ||= full_name.split("::").reject(&:empty?)
455
328
  end
456
329
 
457
- array[9].each do |name, document, file|
458
- ext = add_extend RDoc::Extend.new(name, RDoc::Comment.from_document(document))
459
- ext.record_location RDoc::TopLevel.new file
460
- end if array[9] # Support Marshal version 1
330
+ ##
331
+ # Return array of fully qualified nesting namespaces.
332
+ #
333
+ # For example, if full_name is +A::B::C+, this method returns <code>["A", "A::B", "A::B::C"]</code>
461
334
 
462
- sections = (array[10] || []).map do |section|
463
- [section.title, section]
335
+ def fully_qualified_nesting_namespaces
336
+ return nesting_namespaces if nesting_namespaces.length < 2
337
+ @fqns ||= nesting_namespaces.inject([]) do |list, n|
338
+ list << (list.empty? ? n : "#{list.last}::#{n}")
339
+ end
464
340
  end
465
341
 
466
- @sections = Hash[*sections.flatten]
467
- @current_section = add_section nil
342
+ ##
343
+ # TODO: filter included items by #display?
468
344
 
469
- @in_files = []
345
+ def marshal_dump # :nodoc:
346
+ attrs = attributes.sort.map do |attr|
347
+ next unless attr.display?
348
+ [ attr.name, attr.rw,
349
+ attr.visibility, attr.singleton, attr.file_name,
350
+ ]
351
+ end.compact
470
352
 
471
- (array[11] || []).each do |filename|
472
- record_location RDoc::TopLevel.new filename
473
- end
474
-
475
- @parent_name = array[12]
476
- @parent_class = array[13]
477
- end
353
+ method_types = methods_by_type.map do |type, visibilities|
354
+ visibilities = visibilities.map do |visibility, methods|
355
+ method_names = methods.map do |method|
356
+ next unless method.display?
357
+ [method.name, method.file_name]
358
+ end.compact
478
359
 
479
- ##
480
- # Merges +class_module+ into this ClassModule.
481
- #
482
- # The data in +class_module+ is preferred over the receiver.
360
+ [visibility, method_names.uniq]
361
+ end
483
362
 
484
- def merge(class_module)
485
- @parent = class_module.parent
486
- @parent_name = class_module.parent_name
363
+ [type, visibilities]
364
+ end
487
365
 
488
- other_document = parse class_module.comment_location
366
+ [ MARSHAL_VERSION,
367
+ @name,
368
+ full_name,
369
+ @superclass,
370
+ parse(@comment_location),
371
+ attrs,
372
+ constants.select { |constant| constant.display? },
373
+ includes.map do |incl|
374
+ next unless incl.display?
375
+ [incl.name, parse(incl.comment), incl.file_name]
376
+ end.compact,
377
+ method_types,
378
+ extends.map do |ext|
379
+ next unless ext.display?
380
+ [ext.name, parse(ext.comment), ext.file_name]
381
+ end.compact,
382
+ @sections.values,
383
+ @in_files.map do |tl|
384
+ tl.relative_name
385
+ end,
386
+ parent.full_name,
387
+ parent.class,
388
+ ]
389
+ end
489
390
 
490
- if other_document then
491
- document = parse @comment_location
391
+ def marshal_load(array) # :nodoc:
392
+ initialize_visibility
393
+ initialize_methods_etc
394
+ @current_section = nil
395
+ @document_self = true
396
+ @done_documenting = false
397
+ @parent = nil
398
+ @temporary_section = nil
399
+ @classes = {}
400
+ @modules = {}
492
401
 
493
- document = document.merge other_document
402
+ @name = array[1]
403
+ @full_name = array[2]
404
+ @superclass = array[3]
405
+ document = array[4]
494
406
 
495
- @comment = RDoc::Comment.from_document(document)
407
+ @comment = Comment.from_document document
496
408
 
497
- @comment_location = if document.parts.first.is_a?(RDoc::Markup::Document)
498
- document.parts.map { |doc| [doc, doc.file] }
409
+ @comment_location = if document.parts.first.is_a?(Markup::Document)
410
+ document.parts.group_by(&:file)
499
411
  else
500
- [[document, document.file]]
412
+ { document.file => [document] }
501
413
  end
502
- end
503
414
 
504
- cm = class_module
505
- other_files = cm.in_files
415
+ array[5].each do |name, rw, visibility, singleton, file|
416
+ singleton ||= false
417
+ visibility ||= :public
418
+
419
+ attr = Attr.new name, rw, nil, singleton: singleton
506
420
 
507
- merge_collections attributes, cm.attributes, other_files do |add, attr|
508
- if add then
509
421
  add_attribute attr
510
- else
511
- @attributes.delete attr
512
- @methods_hash.delete attr.pretty_name
422
+ attr.visibility = visibility
423
+ attr.record_location TopLevel.new file
513
424
  end
514
- end
515
425
 
516
- merge_collections constants, cm.constants, other_files do |add, const|
517
- if add then
518
- add_constant const
519
- else
520
- @constants.delete const
521
- @constants_hash.delete const.name
426
+ array[6].each do |constant, document, file|
427
+ case constant
428
+ when Constant
429
+ add_constant constant
430
+ else
431
+ constant = add_constant Constant.new(constant, nil, Comment.from_document(document))
432
+ constant.record_location TopLevel.new file
433
+ end
522
434
  end
523
- end
524
435
 
525
- merge_collections includes, cm.includes, other_files do |add, incl|
526
- if add then
527
- add_include incl
528
- else
529
- @includes.delete incl
436
+ array[7].each do |name, document, file|
437
+ incl = add_include Include.new(name, Comment.from_document(document))
438
+ incl.record_location TopLevel.new file
530
439
  end
531
- end
532
440
 
533
- @includes.uniq! # clean up
441
+ array[8].each do |type, visibilities|
442
+ visibilities.each do |visibility, methods|
443
+ methods.each do |name, file|
444
+ method = AnyMethod.new name, singleton: type == 'class'
445
+ method.record_location TopLevel.new file
446
+ method.visibility = visibility
447
+ add_method method
448
+ end
449
+ end
450
+ end
534
451
 
535
- merge_collections extends, cm.extends, other_files do |add, ext|
536
- if add then
537
- add_extend ext
538
- else
539
- @extends.delete ext
452
+ array[9].each do |name, document, file|
453
+ ext = add_extend Extend.new(name, Comment.from_document(document))
454
+ ext.record_location TopLevel.new file
455
+ end if array[9] # Support Marshal version 1
456
+
457
+ sections = (array[10] || []).map do |section|
458
+ [section.title, section]
540
459
  end
541
- end
542
460
 
543
- @extends.uniq! # clean up
461
+ @sections = Hash[*sections.flatten]
462
+ @current_section = add_section nil
544
463
 
545
- merge_collections method_list, cm.method_list, other_files do |add, meth|
546
- if add then
547
- add_method meth
548
- else
549
- @method_list.delete meth
550
- @methods_hash.delete meth.pretty_name
464
+ @in_files = []
465
+
466
+ (array[11] || []).each do |filename|
467
+ record_location TopLevel.new filename
551
468
  end
469
+
470
+ @parent_name = array[12]
471
+ @parent_class = array[13]
552
472
  end
553
473
 
554
- merge_sections cm
474
+ ##
475
+ # Merges +class_module+ into this ClassModule.
476
+ #
477
+ # The data in +class_module+ is preferred over the receiver.
555
478
 
556
- self
557
- end
479
+ def merge(class_module)
480
+ @parent = class_module.parent
481
+ @parent_name = class_module.parent_name
558
482
 
559
- ##
560
- # Merges collection +mine+ with +other+ preferring other. +other_files+ is
561
- # used to help determine which items should be deleted.
562
- #
563
- # Yields whether the item should be added or removed (true or false) and the
564
- # item to be added or removed.
565
- #
566
- # merge_collections things, other.things, other.in_files do |add, thing|
567
- # if add then
568
- # # add the thing
569
- # else
570
- # # remove the thing
571
- # end
572
- # end
573
-
574
- def merge_collections(mine, other, other_files, &block) # :nodoc:
575
- my_things = mine. group_by { |thing| thing.file }
576
- other_things = other.group_by { |thing| thing.file }
577
-
578
- remove_things my_things, other_files, &block
579
- add_things my_things, other_things, &block
580
- end
483
+ other_document = parse class_module.comment_location
581
484
 
582
- ##
583
- # Merges the comments in this ClassModule with the comments in the other
584
- # ClassModule +cm+.
485
+ if other_document
486
+ document = parse @comment_location
585
487
 
586
- def merge_sections(cm) # :nodoc:
587
- my_sections = sections.group_by { |section| section.title }
588
- other_sections = cm.sections.group_by { |section| section.title }
488
+ document = document.merge other_document
589
489
 
590
- other_files = cm.in_files
490
+ @comment = Comment.from_document(document)
591
491
 
592
- remove_things my_sections, other_files do |_, section|
593
- @sections.delete section.title
594
- end
492
+ @comment_location = if document.parts.first.is_a?(Markup::Document)
493
+ document.parts.group_by(&:file)
494
+ else
495
+ { document.file => [document] }
496
+ end
497
+ end
595
498
 
596
- other_sections.each do |group, sections|
597
- if my_sections.include? group
598
- my_sections[group].each do |my_section|
599
- other_section = cm.sections_hash[group]
499
+ cm = class_module
500
+ other_files = cm.in_files
600
501
 
601
- my_comments = my_section.comments
602
- other_comments = other_section.comments
502
+ merge_collections attributes, cm.attributes, other_files do |add, attr|
503
+ if add
504
+ add_attribute attr
505
+ else
506
+ @attributes.delete attr
507
+ @methods_hash.delete attr.pretty_name
508
+ end
509
+ end
603
510
 
604
- other_files = other_section.in_files
511
+ merge_collections constants, cm.constants, other_files do |add, const|
512
+ if add
513
+ add_constant const
514
+ else
515
+ @constants.delete const
516
+ @constants_hash.delete const.name
517
+ end
518
+ end
605
519
 
606
- merge_collections my_comments, other_comments, other_files do |add, comment|
607
- if add then
608
- my_section.add_comment comment
609
- else
610
- my_section.remove_comment comment
611
- end
612
- end
520
+ merge_collections includes, cm.includes, other_files do |add, incl|
521
+ if add
522
+ add_include incl
523
+ else
524
+ @includes.delete incl
613
525
  end
614
- else
615
- sections.each do |section|
616
- add_section group, section.comments
526
+ end
527
+
528
+ @includes.uniq! # clean up
529
+
530
+ merge_collections extends, cm.extends, other_files do |add, ext|
531
+ if add
532
+ add_extend ext
533
+ else
534
+ @extends.delete ext
617
535
  end
618
536
  end
619
- end
620
- end
621
537
 
622
- ##
623
- # Does this object represent a module?
538
+ @extends.uniq! # clean up
624
539
 
625
- def module?
626
- false
627
- end
540
+ merge_collections method_list, cm.method_list, other_files do |add, meth|
541
+ if add
542
+ add_method meth
543
+ else
544
+ @method_list.delete meth
545
+ @methods_hash.delete meth.pretty_name
546
+ end
547
+ end
628
548
 
629
- ##
630
- # Allows overriding the initial name.
631
- #
632
- # Used for modules and classes that are constant aliases.
549
+ merge_sections cm
633
550
 
634
- def name=(new_name)
635
- @name = new_name
636
- end
551
+ self
552
+ end
637
553
 
638
- ##
639
- # Parses +comment_location+ into an RDoc::Markup::Document composed of
640
- # multiple RDoc::Markup::Documents with their file set.
554
+ ##
555
+ # Merges collection +mine+ with +other+ preferring other. +other_files+ is
556
+ # used to help determine which items should be deleted.
557
+ #
558
+ # Yields whether the item should be added or removed (true or false) and the
559
+ # item to be added or removed.
560
+ #
561
+ # merge_collections things, other.things, other.in_files do |add, thing|
562
+ # if add
563
+ # # add the thing
564
+ # else
565
+ # # remove the thing
566
+ # end
567
+ # end
641
568
 
642
- def parse(comment_location)
643
- case comment_location
644
- when String then
645
- super
646
- when Array then
647
- docs = comment_location.map do |comment, location|
648
- doc = super comment
649
- doc.file = location
650
- doc
651
- end
569
+ def merge_collections(mine, other, other_files, &block) # :nodoc:
570
+ my_things = mine. group_by { |thing| thing.file }
571
+ other_things = other.group_by { |thing| thing.file }
652
572
 
653
- RDoc::Markup::Document.new(*docs)
654
- when RDoc::Comment then
655
- doc = super comment_location.text, comment_location.format
656
- doc.file = comment_location.location
657
- doc
658
- when RDoc::Markup::Document then
659
- return comment_location
660
- else
661
- raise ArgumentError, "unknown comment class #{comment_location.class}"
573
+ remove_things my_things, other_files, &block
574
+ add_things my_things, other_things, &block
662
575
  end
663
- end
664
576
 
665
- ##
666
- # Path to this class or module for use with HTML generator output.
577
+ ##
578
+ # Merges the comments in this ClassModule with the comments in the other
579
+ # ClassModule +cm+.
667
580
 
668
- def path
669
- prefix = options.class_module_path_prefix
670
- return http_url unless prefix
671
- File.join(prefix, http_url)
672
- end
581
+ def merge_sections(cm) # :nodoc:
582
+ my_sections = sections.group_by { |section| section.title }
583
+ other_sections = cm.sections.group_by { |section| section.title }
673
584
 
674
- ##
675
- # Name to use to generate the url:
676
- # modules and classes that are aliases for another
677
- # module or class return the name of the latter.
585
+ other_files = cm.in_files
678
586
 
679
- def name_for_path
680
- is_alias_for ? is_alias_for.full_name : full_name
681
- end
587
+ remove_things my_sections, other_files do |_, section|
588
+ @sections.delete section.title
589
+ end
682
590
 
683
- ##
684
- # Returns the classes and modules that are not constants
685
- # aliasing another class or module. For use by formatters
686
- # only (caches its result).
591
+ other_sections.each do |group, sections|
592
+ if my_sections.include? group
593
+ my_sections[group].each do |my_section|
594
+ other_section = cm.sections_hash[group]
687
595
 
688
- def non_aliases
689
- @non_aliases ||= classes_and_modules.reject { |cm| cm.is_alias_for }
690
- end
596
+ my_comments = my_section.comments
597
+ other_comments = other_section.comments
691
598
 
692
- ##
693
- # Updates the child modules or classes of class/module +parent+ by
694
- # deleting the ones that have been removed from the documentation.
695
- #
696
- # +parent_hash+ is either <tt>parent.modules_hash</tt> or
697
- # <tt>parent.classes_hash</tt> and +all_hash+ is ::all_modules_hash or
698
- # ::all_classes_hash.
599
+ other_files = other_section.in_files
600
+
601
+ merge_collections my_comments, other_comments, other_files do |add, comment|
602
+ if add
603
+ my_section.add_comment comment
604
+ else
605
+ my_section.remove_comment comment
606
+ end
607
+ end
608
+ end
609
+ else
610
+ sections.each do |section|
611
+ add_section group, section.comments
612
+ end
613
+ end
614
+ end
615
+ end
699
616
 
700
- def remove_nodoc_children
701
- prefix = self.full_name + '::'
617
+ ##
618
+ # Does this object represent a module?
702
619
 
703
- modules_hash.each_key do |name|
704
- full_name = prefix + name
705
- modules_hash.delete name unless @store.modules_hash[full_name]
620
+ def module?
621
+ false
706
622
  end
707
623
 
708
- classes_hash.each_key do |name|
709
- full_name = prefix + name
710
- classes_hash.delete name unless @store.classes_hash[full_name]
624
+ ##
625
+ # Allows overriding the initial name.
626
+ #
627
+ # Used for modules and classes that are constant aliases.
628
+
629
+ def name=(new_name)
630
+ @name = new_name
711
631
  end
712
- end
713
632
 
714
- def remove_things(my_things, other_files) # :nodoc:
715
- my_things.delete_if do |file, things|
716
- next false unless other_files.include? file
633
+ ##
634
+ # Parses +comment_location+ into an RDoc::Markup::Document composed of
635
+ # multiple RDoc::Markup::Documents with their file set.
636
+
637
+ def parse(comment_location)
638
+ case comment_location
639
+ when String
640
+ super
641
+ when Hash
642
+ docs = comment_location.flat_map do |location, comments|
643
+ comments.map do |comment|
644
+ doc = super comment
645
+ doc.file = location
646
+ doc
647
+ end
648
+ end
717
649
 
718
- things.each do |thing|
719
- yield false, thing
650
+ Markup::Document.new(*docs)
651
+ when Comment
652
+ doc = super comment_location.text, comment_location.format
653
+ doc.file = comment_location.location
654
+ doc
655
+ when Markup::Document
656
+ return comment_location
657
+ else
658
+ raise ArgumentError, "unknown comment class #{comment_location.class}"
720
659
  end
660
+ end
661
+
662
+ ##
663
+ # Path to this class or module for use with HTML generator output.
721
664
 
722
- true
665
+ def path
666
+ prefix = options.class_module_path_prefix
667
+ return http_url unless prefix
668
+ File.join(prefix, http_url)
723
669
  end
724
- end
725
670
 
726
- ##
727
- # Search record used by RDoc::Generator::JsonIndex
728
- #
729
- # TODO: Remove this method after dropping the darkfish theme and JsonIndex generator.
730
- # Use #search_snippet instead for getting documentation snippets.
731
-
732
- def search_record
733
- [
734
- name,
735
- full_name,
736
- full_name,
737
- '',
738
- path,
739
- '',
740
- snippet(@comment_location),
741
- ]
742
- end
671
+ ##
672
+ # Name to use to generate the url:
673
+ # modules and classes that are aliases for another
674
+ # module or class return the name of the latter.
743
675
 
744
- ##
745
- # Returns an HTML snippet of the first comment for search results.
676
+ def name_for_path
677
+ is_alias_for ? is_alias_for.name_for_path : full_name
678
+ end
746
679
 
747
- def search_snippet
748
- first_comment = @comment_location.first&.first
749
- return '' unless first_comment && !first_comment.empty?
680
+ ##
681
+ # Returns the classes and modules that are not constants
682
+ # aliasing another class or module. For use by formatters
683
+ # only (caches its result).
750
684
 
751
- snippet(first_comment)
752
- end
685
+ def non_aliases
686
+ @non_aliases ||= classes_and_modules.reject { |cm| cm.is_alias_for }
687
+ end
753
688
 
754
- ##
755
- # Sets the store for this class or module and its contained code objects.
689
+ ##
690
+ # Updates the child modules or classes of class/module +parent+ by
691
+ # deleting the ones that have been removed from the documentation.
692
+ #
693
+ # +parent_hash+ is either <tt>parent.modules_hash</tt> or
694
+ # <tt>parent.classes_hash</tt> and +all_hash+ is ::all_modules_hash or
695
+ # ::all_classes_hash.
756
696
 
757
- def store=(store)
758
- super
697
+ def remove_nodoc_children
698
+ prefix = self.full_name + '::'
759
699
 
760
- @attributes .each do |attr| attr.store = store end
761
- @constants .each do |const| const.store = store end
762
- @includes .each do |incl| incl.store = store end
763
- @extends .each do |ext| ext.store = store end
764
- @method_list.each do |meth| meth.store = store end
765
- end
700
+ modules_hash.each_key do |name|
701
+ full_name = prefix + name
702
+ modules_hash.delete name unless @store.modules_hash[full_name]
703
+ end
766
704
 
767
- ##
768
- # Get the superclass of this class. Attempts to retrieve the superclass
769
- # object, returns the name if it is not known.
705
+ classes_hash.each_key do |name|
706
+ full_name = prefix + name
707
+ classes_hash.delete name unless @store.classes_hash[full_name]
708
+ end
709
+ end
770
710
 
771
- def superclass
772
- @store.find_class_named(@superclass) || @superclass
773
- end
711
+ def remove_things(my_things, other_files) # :nodoc:
712
+ my_things.delete_if do |file, things|
713
+ next false unless other_files.include? file
774
714
 
775
- ##
776
- # Set the superclass of this class to +superclass+
777
- #
778
- # where +superclass+ is one of:
779
- #
780
- # - +nil+
781
- # - a String containing the full name of the superclass
782
- # - the RDoc::ClassModule representing the superclass
783
-
784
- def superclass=(superclass)
785
- raise NoMethodError, "#{full_name} is a module" if module?
786
- case superclass
787
- when RDoc::ClassModule
788
- @superclass = superclass.full_name
789
- when nil, String
790
- @superclass = superclass
791
- else
792
- raise TypeError, "superclass must be a String or RDoc::ClassModule, not #{superclass.class}"
715
+ things.each do |thing|
716
+ yield false, thing
717
+ end
718
+
719
+ true
720
+ end
793
721
  end
794
- end
795
722
 
796
- ##
797
- # Get all super classes of this class in an array. The last element might be
798
- # a string if the name is unknown.
723
+ ##
724
+ # Search record used by RDoc::Generator::JsonIndex
725
+ #
726
+ # TODO: Remove this method after dropping the darkfish theme and JsonIndex generator.
727
+ # Use #search_snippet instead for getting documentation snippets.
728
+
729
+ def search_record
730
+ [
731
+ name,
732
+ full_name,
733
+ full_name,
734
+ '',
735
+ path,
736
+ '',
737
+ snippet(@comment_location),
738
+ ]
739
+ end
799
740
 
800
- def super_classes
801
- result = []
802
- parent = self
803
- while parent = parent.superclass
804
- result << parent
805
- return result if parent.is_a?(String)
741
+ ##
742
+ # Returns an HTML snippet of the first comment for search results.
743
+
744
+ def search_snippet
745
+ first_comment = @comment_location.each_value.first&.first
746
+ return '' unless first_comment && !first_comment.empty?
747
+
748
+ snippet(first_comment)
806
749
  end
807
- result
808
- end
809
750
 
810
- def to_s # :nodoc:
811
- if is_alias_for then
812
- "#{self.class.name} #{self.full_name} -> #{is_alias_for}"
813
- else
814
- super
751
+ ##
752
+ # Rebuilds +@comment+ from the current +@comment_location+ entries,
753
+ # skipping any empty placeholders.
754
+
755
+ def rebuild_comment_from_location
756
+ texts = @comment_location.each_value.flat_map { |comments|
757
+ comments.filter_map { |c| c.to_s unless c.empty? }
758
+ }
759
+ merged = texts.join("\n---\n")
760
+ @comment = merged.empty? ? '' : Comment.new(merged)
815
761
  end
816
- end
817
762
 
818
- ##
819
- # 'module' or 'class'
763
+ ##
764
+ # Sets the store for this class or module and its contained code objects.
820
765
 
821
- def type
822
- module? ? 'module' : 'class'
823
- end
766
+ def store=(store)
767
+ super
824
768
 
825
- ##
826
- # Updates the child modules & classes by replacing the ones that are
827
- # aliases through a constant.
828
- #
829
- # The aliased module/class is replaced in the children and in
830
- # RDoc::Store#modules_hash or RDoc::Store#classes_hash
831
- # by a copy that has <tt>RDoc::ClassModule#is_alias_for</tt> set to
832
- # the aliased module/class, and this copy is added to <tt>#aliases</tt>
833
- # of the aliased module/class.
834
- #
835
- # Formatters can use the #non_aliases method to retrieve children that
836
- # are not aliases, for instance to list the namespace content, since
837
- # the aliased modules are included in the constants of the class/module,
838
- # that are listed separately.
839
-
840
- def update_aliases
841
- constants.each do |const|
842
- next unless cm = const.is_alias_for
843
- cm_alias = cm.dup
844
- cm_alias.name = const.name
845
-
846
- if full_name == 'Object'
847
- # Don't move top-level aliases under Object, they look ugly there
848
- cm_alias.parent = top_level
769
+ @attributes .each do |attr| attr.store = store end
770
+ @constants .each do |const| const.store = store end
771
+ @includes .each do |incl| incl.store = store end
772
+ @extends .each do |ext| ext.store = store end
773
+ @method_list.each do |meth| meth.store = store end
774
+ end
775
+
776
+ ##
777
+ # Get the superclass of this class. Attempts to retrieve the superclass
778
+ # object, returns the name if it is not known.
779
+
780
+ def superclass
781
+ @store.find_class_named(@superclass) || @superclass
782
+ end
783
+
784
+ ##
785
+ # Set the superclass of this class to +superclass+
786
+ #
787
+ # where +superclass+ is one of:
788
+ #
789
+ # - +nil+
790
+ # - a String containing the full name of the superclass
791
+ # - the RDoc::ClassModule representing the superclass
792
+
793
+ def superclass=(superclass)
794
+ raise NoMethodError, "#{full_name} is a module" if module?
795
+ case superclass
796
+ when ClassModule
797
+ @superclass = superclass.full_name
798
+ when nil, String
799
+ @superclass = superclass
849
800
  else
850
- cm_alias.parent = self
801
+ raise TypeError, "superclass must be a String or RDoc::ClassModule, not #{superclass.class}"
851
802
  end
852
- cm_alias.full_name = nil # force update for new parent
803
+ end
853
804
 
854
- cm_alias.aliases.clear
855
- cm_alias.is_alias_for = cm
805
+ ##
806
+ # Get all super classes of this class in an array. The last element might be
807
+ # a string if the name is unknown.
856
808
 
857
- if cm.module? then
858
- @store.modules_hash[cm_alias.full_name] = cm_alias
859
- modules_hash[const.name] = cm_alias
860
- else
861
- @store.classes_hash[cm_alias.full_name] = cm_alias
862
- classes_hash[const.name] = cm_alias
809
+ def super_classes
810
+ result = []
811
+ # Degenerate input can produce a cyclic superclass chain
812
+ visited = [full_name]
813
+ parent = self
814
+ while parent = parent.superclass
815
+ if parent.is_a?(String)
816
+ result << parent
817
+ break
818
+ end
819
+ break if visited.include?(parent.full_name)
820
+ visited << parent.full_name
821
+ result << parent
863
822
  end
823
+ result
824
+ end
864
825
 
865
- cm.aliases << cm_alias
826
+ def to_s # :nodoc:
827
+ if is_alias_for
828
+ "#{self.class.name} #{self.full_name} -> #{is_alias_for}"
829
+ else
830
+ super
831
+ end
866
832
  end
867
- end
868
833
 
869
- ##
870
- # Deletes from #includes those whose module has been removed from the
871
- # documentation.
872
- #--
873
- # FIXME: includes are not reliably removed, see _possible_bug test case
834
+ ##
835
+ # 'module' or 'class'
836
+
837
+ def type
838
+ module? ? 'module' : 'class'
839
+ end
840
+
841
+ ##
842
+ # Updates the child modules & classes by replacing the ones that are
843
+ # aliases through a constant.
844
+ #
845
+ # The aliased module/class is replaced in the children and in
846
+ # RDoc::Store#modules_hash or RDoc::Store#classes_hash
847
+ # by a copy that has <tt>RDoc::ClassModule#is_alias_for</tt> set to
848
+ # the aliased module/class, and this copy is added to <tt>#aliases</tt>
849
+ # of the aliased module/class.
850
+ #
851
+ # Formatters can use the #non_aliases method to retrieve children that
852
+ # are not aliases, for instance to list the namespace content, since
853
+ # the aliased modules are included in the constants of the class/module,
854
+ # that are listed separately.
855
+
856
+ def update_aliases
857
+ constants.each do |const|
858
+ cm = const.is_alias_for
859
+ cm ||= const.resolved_alias_target if const.is_a?(Constant)
860
+ next unless cm
861
+
862
+ # Resolve chained aliases (A = B = C) to the real class/module.
863
+ cm = @store.find_class_or_module(cm.full_name) || cm
864
+ while (target = cm.is_alias_for)
865
+ cm = target
866
+ end
874
867
 
875
- def update_includes
876
- includes.reject! do |include|
877
- mod = include.module
878
- !(String === mod) && @store.modules_hash[mod.full_name].nil?
879
- end
868
+ cm_alias = cm.dup
869
+ cm_alias.name = const.name
880
870
 
881
- includes.uniq!
882
- end
871
+ if full_name == 'Object'
872
+ # Don't move top-level aliases under Object, they look ugly there
873
+ cm_alias.parent = top_level
874
+ else
875
+ cm_alias.parent = self
876
+ end
877
+ cm_alias.full_name = nil # force update for new parent
878
+
879
+ # Don't clobber a real (non-alias) class/module already living at this
880
+ # name. Mirrors the BasicObject = BlankSlate guard in
881
+ # Context#add_module_alias. Existing alias copies (set by
882
+ # add_module_alias or a previous update_aliases pass) carry is_alias_for,
883
+ # so they're still overwritable here.
884
+ existing = @store.find_class_or_module(cm_alias.full_name)
885
+ next if existing && !existing.is_alias_for
886
+
887
+ # Persist a lazy-resolved target so Stats#report_constants and
888
+ # Constant#marshal_dump observe the alias relationship. Skipped
889
+ # aliases (above) intentionally leave the constant unmarked.
890
+ const.is_alias_for ||= cm
891
+
892
+ cm_alias.aliases.clear
893
+ cm_alias.is_alias_for = cm
894
+
895
+ if cm.module?
896
+ @store.modules_hash[cm_alias.full_name] = cm_alias
897
+ modules_hash[const.name] = cm_alias
898
+ else
899
+ @store.classes_hash[cm_alias.full_name] = cm_alias
900
+ classes_hash[const.name] = cm_alias
901
+ end
883
902
 
884
- ##
885
- # Deletes from #extends those whose module has been removed from the
886
- # documentation.
887
- #--
888
- # FIXME: like update_includes, extends are not reliably removed
903
+ cm.aliases << cm_alias
904
+ end
905
+ end
906
+
907
+ ##
908
+ # Deletes from #includes those whose module has been removed from the
909
+ # documentation.
910
+ #--
911
+ # FIXME: includes are not reliably removed, see _possible_bug test case
889
912
 
890
- def update_extends
891
- extends.reject! do |ext|
892
- mod = ext.module
913
+ def update_includes
914
+ includes.reject! do |include|
915
+ mod = include.module
916
+ !(String === mod) && @store.modules_hash[mod.full_name].nil?
917
+ end
893
918
 
894
- !(String === mod) && @store.modules_hash[mod.full_name].nil?
919
+ includes.uniq!
895
920
  end
896
921
 
897
- extends.uniq!
898
- end
922
+ ##
923
+ # Deletes from #extends those whose module has been removed from the
924
+ # documentation.
925
+ #--
926
+ # FIXME: like update_includes, extends are not reliably removed
899
927
 
900
- def embed_mixins
901
- return unless options.embed_mixins
928
+ def update_extends
929
+ extends.reject! do |ext|
930
+ mod = ext.module
902
931
 
903
- includes.each do |include|
904
- next if String === include.module
905
- include.module.method_list.each do |code_object|
906
- add_method(prepare_to_embed(code_object))
907
- end
908
- include.module.constants.each do |code_object|
909
- add_constant(prepare_to_embed(code_object))
910
- end
911
- include.module.attributes.each do |code_object|
912
- add_attribute(prepare_to_embed(code_object))
932
+ !(String === mod) && @store.modules_hash[mod.full_name].nil?
913
933
  end
934
+
935
+ extends.uniq!
914
936
  end
915
937
 
916
- extends.each do |ext|
917
- next if String === ext.module
918
- ext.module.method_list.each do |code_object|
919
- add_method(prepare_to_embed(code_object, true))
938
+ def embed_mixins
939
+ return unless options.embed_mixins
940
+
941
+ includes.each do |include|
942
+ next if String === include.module
943
+ include.module.method_list.each do |code_object|
944
+ add_method(prepare_to_embed(code_object))
945
+ end
946
+ include.module.constants.each do |code_object|
947
+ add_constant(prepare_to_embed(code_object))
948
+ end
949
+ include.module.attributes.each do |code_object|
950
+ add_attribute(prepare_to_embed(code_object))
951
+ end
920
952
  end
921
- ext.module.attributes.each do |code_object|
922
- add_attribute(prepare_to_embed(code_object, true))
953
+
954
+ extends.each do |ext|
955
+ next if String === ext.module
956
+ ext.module.method_list.each do |code_object|
957
+ add_method(prepare_to_embed(code_object, true))
958
+ end
959
+ ext.module.attributes.each do |code_object|
960
+ add_attribute(prepare_to_embed(code_object, true))
961
+ end
923
962
  end
924
963
  end
925
- end
926
964
 
927
965
  private
928
966
 
929
- def prepare_to_embed(code_object, singleton=false)
930
- code_object = code_object.dup
931
- code_object.mixin_from = code_object.parent
932
- code_object.singleton = true if singleton
933
- set_current_section(code_object.section.title, code_object.section.comment)
934
- # add_method and add_attribute will reassign self's visibility back to the method/attribute
935
- # so we need to sync self's visibility with the object's to properly retain that information
936
- self.visibility = code_object.visibility
937
- code_object
967
+ def prepare_to_embed(code_object, singleton=false)
968
+ code_object = code_object.dup
969
+ code_object.mixin_from = code_object.parent
970
+ code_object.singleton = true if singleton
971
+ set_current_section(code_object.section.title, code_object.section.comment)
972
+ code_object
973
+ end
938
974
  end
939
975
  end