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/stats.rb CHANGED
@@ -1,461 +1,486 @@
1
1
  # frozen_string_literal: true
2
- ##
3
- # RDoc statistics collector which prints a summary and report of a project's
4
- # documentation totals.
5
-
6
- class RDoc::Stats
7
-
8
- include RDoc::Text
9
-
2
+ module RDoc
10
3
  ##
11
- # Output level for the coverage report
4
+ # RDoc statistics collector which prints a summary and report of a project's
5
+ # documentation totals.
12
6
 
13
- attr_reader :coverage_level
7
+ class Stats
14
8
 
15
- ##
16
- # Count of files parsed during parsing
9
+ include Text
17
10
 
18
- attr_reader :files_so_far
11
+ ##
12
+ # Display order for item types in the coverage report
19
13
 
20
- ##
21
- # Total number of files found
14
+ TYPE_ORDER = %w[Class Module Constant Attribute Method].freeze
22
15
 
23
- attr_reader :num_files
16
+ ##
17
+ # Message displayed when all items are documented
24
18
 
25
- ##
26
- # Creates a new Stats that will have +num_files+. +verbosity+ defaults to 1
27
- # which will create an RDoc::Stats::Normal outputter.
28
-
29
- def initialize(store, num_files, verbosity = 1)
30
- @num_files = num_files
31
- @store = store
32
-
33
- @coverage_level = 0
34
- @doc_items = nil
35
- @files_so_far = 0
36
- @fully_documented = false
37
- @num_params = 0
38
- @percent_doc = nil
39
- @start = Time.now
40
- @undoc_params = 0
41
-
42
- @display = case verbosity
43
- when 0 then Quiet.new num_files
44
- when 1 then Normal.new num_files
45
- else Verbose.new num_files
46
- end
47
- end
19
+ GREAT_JOB_MESSAGE = <<~MSG
20
+ 100% documentation!
21
+ Great Job!
22
+ MSG
48
23
 
49
- ##
50
- # Records the parsing of an alias +as+.
51
-
52
- def add_alias(as)
53
- @display.print_alias as
54
- end
24
+ ##
25
+ # Output level for the coverage report
55
26
 
56
- ##
57
- # Records the parsing of an attribute +attribute+
27
+ attr_reader :coverage_level
58
28
 
59
- def add_attribute(attribute)
60
- @display.print_attribute attribute
61
- end
29
+ ##
30
+ # Count of files parsed during parsing
62
31
 
63
- ##
64
- # Records the parsing of a class +klass+
32
+ attr_reader :files_so_far
65
33
 
66
- def add_class(klass)
67
- @display.print_class klass
68
- end
34
+ ##
35
+ # Total number of files found
69
36
 
70
- ##
71
- # Records the parsing of +constant+
37
+ attr_reader :num_files
72
38
 
73
- def add_constant(constant)
74
- @display.print_constant constant
75
- end
39
+ ##
40
+ # Creates a new Stats that will have +num_files+. +verbosity+ defaults to 1
41
+ # which will create an RDoc::Stats::Normal outputter.
76
42
 
77
- ##
78
- # Records the parsing of +file+
43
+ def initialize(store, num_files, verbosity = 1)
44
+ @num_files = num_files
45
+ @store = store
79
46
 
80
- def add_file(file)
81
- @files_so_far += 1
82
- @display.print_file @files_so_far, file
83
- end
47
+ @coverage_level = 0
48
+ @doc_items = nil
49
+ @files_so_far = 0
50
+ @fully_documented = false
51
+ @num_params = 0
52
+ @percent_doc = nil
53
+ @start = Time.now
54
+ @undoc_params = 0
84
55
 
85
- ##
86
- # Records the parsing of +method+
56
+ self.verbosity = verbosity
57
+ end
87
58
 
88
- def add_method(method)
89
- @display.print_method method
90
- end
59
+ ##
60
+ # Sets the verbosity level, rebuilding the display outputter.
91
61
 
92
- ##
93
- # Records the parsing of a module +mod+
62
+ def verbosity=(verbosity)
63
+ @display = case verbosity
64
+ when 0 then Quiet.new @num_files
65
+ when 1 then Normal.new @num_files
66
+ else Verbose.new @num_files
67
+ end
68
+ end
94
69
 
95
- def add_module(mod)
96
- @display.print_module mod
97
- end
70
+ ##
71
+ # Records the parsing of an alias +as+.
98
72
 
99
- ##
100
- # Call this to mark the beginning of parsing for display purposes
73
+ def add_alias(as)
74
+ @display.print_alias as
75
+ end
101
76
 
102
- def begin_adding
103
- @display.begin_adding
104
- end
77
+ ##
78
+ # Records the parsing of an attribute +attribute+
105
79
 
106
- ##
107
- # Calculates documentation totals and percentages for classes, modules,
108
- # constants, attributes and methods.
80
+ def add_attribute(attribute)
81
+ @display.print_attribute attribute
82
+ end
109
83
 
110
- def calculate
111
- return if @doc_items
84
+ ##
85
+ # Records the parsing of a class +klass+
112
86
 
113
- ucm = @store.unique_classes_and_modules
87
+ def add_class(klass)
88
+ @display.print_class klass
89
+ end
114
90
 
115
- classes = @store.unique_classes.reject { |cm| cm.full_name == 'Object' }
91
+ ##
92
+ # Records the parsing of +constant+
116
93
 
117
- constants = []
118
- ucm.each { |cm| constants.concat cm.constants }
94
+ def add_constant(constant)
95
+ @display.print_constant constant
96
+ end
119
97
 
120
- methods = []
121
- ucm.each { |cm| methods.concat cm.method_list }
98
+ ##
99
+ # Records the parsing of +file+
122
100
 
123
- attributes = []
124
- ucm.each { |cm| attributes.concat cm.attributes }
101
+ def add_file(file)
102
+ @files_so_far += 1
103
+ @display.print_file @files_so_far, file
104
+ end
125
105
 
126
- @num_attributes, @undoc_attributes = doc_stats attributes
127
- @num_classes, @undoc_classes = doc_stats classes
128
- @num_constants, @undoc_constants = doc_stats constants
129
- @num_methods, @undoc_methods = doc_stats methods
130
- @num_modules, @undoc_modules = doc_stats @store.unique_modules
106
+ ##
107
+ # Records the parsing of +method+
131
108
 
132
- @num_items =
133
- @num_attributes +
134
- @num_classes +
135
- @num_constants +
136
- @num_methods +
137
- @num_modules +
138
- @num_params
109
+ def add_method(method)
110
+ @display.print_method method
111
+ end
139
112
 
140
- @undoc_items =
141
- @undoc_attributes +
142
- @undoc_classes +
143
- @undoc_constants +
144
- @undoc_methods +
145
- @undoc_modules +
146
- @undoc_params
113
+ ##
114
+ # Records the parsing of a module +mod+
147
115
 
148
- @doc_items = @num_items - @undoc_items
149
- end
116
+ def add_module(mod)
117
+ @display.print_module mod
118
+ end
150
119
 
151
- ##
152
- # Sets coverage report level. Accepted values are:
153
- #
154
- # false or nil:: No report
155
- # 0:: Classes, modules, constants, attributes, methods
156
- # 1:: Level 0 + method parameters
120
+ ##
121
+ # Call this to mark the beginning of parsing for display purposes
157
122
 
158
- def coverage_level=(level)
159
- level = -1 unless level
123
+ def begin_adding
124
+ @display.begin_adding
125
+ end
160
126
 
161
- @coverage_level = level
162
- end
127
+ ##
128
+ # Calculates documentation totals and percentages for classes, modules,
129
+ # constants, attributes and methods.
163
130
 
164
- ##
165
- # Returns the length and number of undocumented items in +collection+.
131
+ def calculate
132
+ return if @doc_items
166
133
 
167
- def doc_stats(collection)
168
- visible = collection.select { |item| item.display? }
169
- [visible.length, visible.count { |item| not item.documented? }]
170
- end
134
+ ucm = @store.unique_classes_and_modules
171
135
 
172
- ##
173
- # Call this to mark the end of parsing for display purposes
136
+ classes = @store.unique_classes.reject { |cm| cm.full_name == 'Object' }
174
137
 
175
- def done_adding
176
- @display.done_adding
177
- end
138
+ constants = []
139
+ ucm.each { |cm| constants.concat cm.constants }
178
140
 
179
- ##
180
- # The documentation status of this project. +true+ when 100%, +false+ when
181
- # less than 100% and +nil+ when unknown.
182
- #
183
- # Set by calling #calculate
141
+ methods = []
142
+ ucm.each { |cm| methods.concat cm.method_list }
184
143
 
185
- def fully_documented?
186
- @fully_documented
187
- end
144
+ attributes = []
145
+ ucm.each { |cm| attributes.concat cm.attributes }
188
146
 
189
- ##
190
- # A report that says you did a great job!
147
+ @num_attributes, @undoc_attributes = doc_stats attributes
148
+ @num_classes, @undoc_classes = doc_stats classes
149
+ @num_constants, @undoc_constants = doc_stats constants
150
+ @num_methods, @undoc_methods = doc_stats methods
151
+ @num_modules, @undoc_modules = doc_stats @store.unique_modules
191
152
 
192
- def great_job
193
- report = RDoc::Markup::Document.new
153
+ @num_items =
154
+ @num_attributes +
155
+ @num_classes +
156
+ @num_constants +
157
+ @num_methods +
158
+ @num_modules +
159
+ @num_params
194
160
 
195
- report << RDoc::Markup::Paragraph.new('100% documentation!')
196
- report << RDoc::Markup::Paragraph.new('Great Job!')
161
+ @undoc_items =
162
+ @undoc_attributes +
163
+ @undoc_classes +
164
+ @undoc_constants +
165
+ @undoc_methods +
166
+ @undoc_modules +
167
+ @undoc_params
197
168
 
198
- report
199
- end
169
+ @doc_items = @num_items - @undoc_items
170
+ end
200
171
 
201
- ##
202
- # Calculates the percentage of items documented.
172
+ ##
173
+ # Sets coverage report level. Accepted values are:
174
+ #
175
+ # false or nil:: No report
176
+ # 0:: Classes, modules, constants, attributes, methods
177
+ # 1:: Level 0 + method parameters
203
178
 
204
- def percent_doc
205
- return @percent_doc if @percent_doc
179
+ def coverage_level=(level)
180
+ level = -1 unless level
206
181
 
207
- @fully_documented = (@num_items - @doc_items) == 0
182
+ @coverage_level = level
183
+ end
208
184
 
209
- @percent_doc = @doc_items.to_f / @num_items * 100 if @num_items.nonzero?
210
- @percent_doc ||= 0
185
+ ##
186
+ # Returns the length and number of undocumented items in +collection+.
211
187
 
212
- @percent_doc
213
- end
188
+ def doc_stats(collection)
189
+ visible = collection.select { |item| item.display? }
190
+ [visible.length, visible.count { |item| not item.documented? }]
191
+ end
214
192
 
215
- ##
216
- # Returns a report on which items are not documented
193
+ ##
194
+ # Call this to mark the end of parsing for display purposes
217
195
 
218
- def report
219
- if @coverage_level > 0 then
220
- extend RDoc::Text
196
+ def done_adding
197
+ @display.done_adding
221
198
  end
222
199
 
223
- if @coverage_level.zero? then
224
- calculate
200
+ ##
201
+ # The documentation status of this project. +true+ when 100%, +false+ when
202
+ # less than 100% and +nil+ when unknown.
203
+ #
204
+ # Set by calling #calculate
225
205
 
226
- return great_job if @num_items == @doc_items
206
+ def fully_documented?
207
+ @fully_documented
227
208
  end
228
209
 
229
- ucm = @store.unique_classes_and_modules
210
+ ##
211
+ # Calculates the percentage of items documented.
212
+
213
+ def percent_doc
214
+ return @percent_doc if @percent_doc
230
215
 
231
- report = RDoc::Markup::Document.new
232
- report << RDoc::Markup::Paragraph.new('The following items are not documented:')
233
- report << RDoc::Markup::BlankLine.new
216
+ @fully_documented = (@num_items - @doc_items) == 0
234
217
 
235
- ucm.sort.each do |cm|
236
- body = report_class_module(cm) {
237
- [
238
- report_constants(cm),
239
- report_attributes(cm),
240
- report_methods(cm),
241
- ].compact
242
- }
218
+ @percent_doc = @doc_items.to_f / @num_items * 100 if @num_items.nonzero?
219
+ @percent_doc ||= 0
243
220
 
244
- report << body if body
221
+ @percent_doc
245
222
  end
246
223
 
247
- if @coverage_level > 0 then
248
- calculate
224
+ ##
225
+ # Returns a report on which items are not documented
249
226
 
250
- return great_job if @num_items == @doc_items
251
- end
227
+ def report
228
+ if @coverage_level > 0
229
+ extend Text
230
+ end
252
231
 
253
- report
254
- end
232
+ if @coverage_level.zero?
233
+ calculate
255
234
 
256
- ##
257
- # Returns a report on undocumented attributes in ClassModule +cm+
235
+ return GREAT_JOB_MESSAGE if @num_items == @doc_items
236
+ end
258
237
 
259
- def report_attributes(cm)
260
- return if cm.attributes.empty?
238
+ items, empty_classes = collect_undocumented_items
261
239
 
262
- report = []
240
+ if @coverage_level > 0
241
+ calculate
263
242
 
264
- cm.attributes.each do |attr|
265
- next if attr.documented?
266
- line = attr.line ? ":#{attr.line}" : nil
267
- report << " #{attr.definition} :#{attr.name} # in file #{attr.file.full_name}#{line}\n"
268
- report << "\n"
269
- end
243
+ return GREAT_JOB_MESSAGE if @num_items == @doc_items
244
+ end
270
245
 
271
- report
272
- end
246
+ report = +""
247
+ report << "The following items are not documented:\n\n"
273
248
 
274
- ##
275
- # Returns a report on undocumented items in ClassModule +cm+
249
+ # Referenced-but-empty classes
250
+ empty_classes.each do |cm|
251
+ report << "#{cm.full_name} is referenced but empty.\n"
252
+ report << "It probably came from another project. I'm sorry I'm holding it against you.\n\n"
253
+ end
276
254
 
277
- def report_class_module(cm)
278
- return if cm.fully_documented? and @coverage_level.zero?
279
- return unless cm.display?
255
+ # Group items by file, then by type
256
+ by_file = items.group_by { |item| item[:file] }
280
257
 
281
- report = RDoc::Markup::Document.new
258
+ by_file.sort_by { |file, _| file }.each do |file, file_items|
259
+ report << "#{file}:\n"
282
260
 
283
- if cm.in_files.empty? then
284
- report << RDoc::Markup::Paragraph.new("#{cm.definition} is referenced but empty.")
285
- report << RDoc::Markup::Paragraph.new("It probably came from another project. I'm sorry I'm holding it against you.")
261
+ by_type = file_items.group_by { |item| item[:type] }
286
262
 
287
- return report
288
- elsif cm.documented? then
289
- documented = true
290
- klass = RDoc::Markup::Verbatim.new("#{cm.definition} # is documented\n")
291
- else
292
- report << RDoc::Markup::Paragraph.new('In files:')
263
+ TYPE_ORDER.each do |type|
264
+ next unless by_type[type]
293
265
 
294
- list = RDoc::Markup::List.new :BULLET
266
+ report << " #{type}:\n"
295
267
 
296
- cm.in_files.each do |file|
297
- para = RDoc::Markup::Paragraph.new file.full_name
298
- list << RDoc::Markup::ListItem.new(nil, para)
299
- end
268
+ sorted = by_type[type].sort_by { |item| [item[:line] || 0, item[:name]] }
269
+ name_width = sorted.reduce(0) { |max, item| item[:line] && item[:name].length > max ? item[:name].length : max }
300
270
 
301
- report << list
302
- report << RDoc::Markup::BlankLine.new
271
+ sorted.each do |item|
272
+ if item[:line]
273
+ report << " %-*s %s:%d\n" % [name_width, item[:name], item[:file], item[:line]]
274
+ else
275
+ report << " #{item[:name]}\n"
276
+ end
277
+
278
+ if item[:undoc_params]
279
+ report << " Undocumented params: #{item[:undoc_params].join(', ')}\n"
280
+ end
281
+ end
282
+ end
303
283
 
304
- klass = RDoc::Markup::Verbatim.new("#{cm.definition}\n")
284
+ report << "\n"
285
+ end
286
+
287
+ report
305
288
  end
306
289
 
307
- klass << "\n"
290
+ ##
291
+ # Collects all undocumented items across all classes and modules.
292
+ # Returns [items, empty_classes] where items is an Array of Hashes
293
+ # with keys :type, :name, :file, :line, and empty_classes is an
294
+ # Array of ClassModule objects that are referenced but have no files.
308
295
 
309
- body = yield.flatten # HACK remove #flatten
296
+ def collect_undocumented_items
297
+ empty_classes = []
298
+ items = []
310
299
 
311
- if body.empty? then
312
- return if documented
300
+ @store.unique_classes_and_modules.each do |class_module|
301
+ next unless class_module.display?
313
302
 
314
- klass.parts.pop
315
- else
316
- klass.parts.concat body
317
- end
303
+ if class_module.in_files.empty?
304
+ empty_classes << class_module
305
+ next
306
+ end
318
307
 
319
- klass << "end\n"
308
+ unless class_module.documented? || class_module.full_name == 'Object'
309
+ collect_undocumented_class_module(class_module, items)
310
+ end
320
311
 
321
- report << klass
312
+ collect_undocumented_constants(class_module, items)
313
+ collect_undocumented_attributes(class_module, items)
314
+ collect_undocumented_methods(class_module, items)
315
+ end
322
316
 
323
- report
324
- end
317
+ [items, empty_classes]
318
+ end
325
319
 
326
- ##
327
- # Returns a report on undocumented constants in ClassModule +cm+
320
+ ##
321
+ # Collects undocumented classes or modules from +class_module+ into +items+.
322
+ # Reopened classes/modules are reported in every file they appear in.
323
+
324
+ def collect_undocumented_class_module(class_module, items)
325
+ class_module.in_files.map(&:full_name).uniq.each do |file|
326
+ items << {
327
+ type: class_module.type.capitalize,
328
+ name: class_module.full_name,
329
+ file: file,
330
+ line: nil,
331
+ }
332
+ end
333
+ end
328
334
 
329
- def report_constants(cm)
330
- return if cm.constants.empty?
335
+ ##
336
+ # Collects undocumented constants from +class_module+ into +items+.
331
337
 
332
- report = []
338
+ def collect_undocumented_constants(class_module, items)
339
+ class_module.constants.each do |constant|
340
+ next unless constant.display?
341
+ next if constant.documented? || constant.is_alias_for
333
342
 
334
- cm.constants.each do |constant|
335
- # TODO constant aliases are listed in the summary but not reported
336
- # figure out what to do here
337
- next if constant.documented? || constant.is_alias_for
343
+ file = constant.file&.full_name
344
+ next unless file
338
345
 
339
- line = constant.line ? ":#{constant.line}" : line
340
- report << " # in file #{constant.file.full_name}#{line}\n"
341
- report << " #{constant.name} = nil\n"
342
- report << "\n"
346
+ items << {
347
+ type: "Constant",
348
+ name: constant.full_name,
349
+ file: file,
350
+ line: constant.line,
351
+ }
352
+ end
343
353
  end
344
354
 
345
- report
346
- end
355
+ ##
356
+ # Collects undocumented attributes from +class_module+ into +items+.
347
357
 
348
- ##
349
- # Returns a report on undocumented methods in ClassModule +cm+
358
+ def collect_undocumented_attributes(class_module, items)
359
+ class_module.attributes.each do |attr|
360
+ next unless attr.display?
361
+ next if attr.documented?
350
362
 
351
- def report_methods(cm)
352
- return if cm.method_list.empty?
363
+ file = attr.file&.full_name
364
+ next unless file
353
365
 
354
- report = []
366
+ scope = attr.singleton ? "." : "#"
367
+ items << {
368
+ type: "Attribute",
369
+ name: "#{class_module.full_name}#{scope}#{attr.name}",
370
+ file: file,
371
+ line: attr.line,
372
+ }
373
+ end
374
+ end
355
375
 
356
- cm.each_method do |method|
357
- next if method.documented? and @coverage_level.zero?
376
+ ##
377
+ # Collects undocumented methods from +class_module+ into +items+.
378
+ # At coverage level > 0, also counts undocumented parameters.
358
379
 
359
- if @coverage_level > 0 then
360
- params, undoc = undoc_params method
380
+ def collect_undocumented_methods(class_module, items)
381
+ class_module.each_method do |method|
382
+ next unless method.display?
383
+ next if method.documented? && @coverage_level.zero?
361
384
 
362
- @num_params += params
385
+ undoc_param_names = nil
363
386
 
364
- unless undoc.empty? then
365
- @undoc_params += undoc.length
387
+ if @coverage_level > 0
388
+ params, undoc = undoc_params method
389
+ @num_params += params
366
390
 
367
- undoc = undoc.map do |param| "+#{param}+" end
368
- param_report = " # #{undoc.join ', '} is not documented\n"
391
+ unless undoc.empty?
392
+ @undoc_params += undoc.length
393
+ undoc_param_names = undoc
394
+ end
369
395
  end
396
+
397
+ next if method.documented? && !undoc_param_names
398
+
399
+ file = method.file&.full_name
400
+ next unless file
401
+
402
+ scope = method.singleton ? "." : "#"
403
+ item = {
404
+ type: "Method",
405
+ name: "#{class_module.full_name}#{scope}#{method.name}",
406
+ file: file,
407
+ line: method.line,
408
+ }
409
+ item[:undoc_params] = undoc_param_names if undoc_param_names
410
+
411
+ items << item
370
412
  end
413
+ end
371
414
 
372
- next if method.documented? and not param_report
415
+ ##
416
+ # Returns a summary of the collected statistics.
373
417
 
374
- line = method.line ? ":#{method.line}" : nil
375
- scope = method.singleton ? 'self.' : nil
418
+ def summary
419
+ calculate
420
+
421
+ num_width = [@num_files, @num_items].max.to_s.length
422
+ undoc_width = [
423
+ @undoc_attributes,
424
+ @undoc_classes,
425
+ @undoc_constants,
426
+ @undoc_items,
427
+ @undoc_methods,
428
+ @undoc_modules,
429
+ @undoc_params,
430
+ ].max.to_s.length
376
431
 
377
- report << " # in file #{method.file.full_name}#{line}\n"
378
- report << param_report if param_report
379
- report << " def #{scope}#{method.name}#{method.params}; end\n"
432
+ report = +""
433
+
434
+ report << "Files: %*d\n" % [num_width, @num_files]
435
+ report << "\n"
436
+ report << "Classes: %*d (%*d undocumented)\n" % [
437
+ num_width, @num_classes, undoc_width, @undoc_classes]
438
+ report << "Modules: %*d (%*d undocumented)\n" % [
439
+ num_width, @num_modules, undoc_width, @undoc_modules]
440
+ report << "Constants: %*d (%*d undocumented)\n" % [
441
+ num_width, @num_constants, undoc_width, @undoc_constants]
442
+ report << "Attributes: %*d (%*d undocumented)\n" % [
443
+ num_width, @num_attributes, undoc_width, @undoc_attributes]
444
+ report << "Methods: %*d (%*d undocumented)\n" % [
445
+ num_width, @num_methods, undoc_width, @undoc_methods]
446
+ report << "Parameters: %*d (%*d undocumented)\n" % [
447
+ num_width, @num_params, undoc_width, @undoc_params] if
448
+ @coverage_level > 0
380
449
  report << "\n"
450
+ report << "Total: %*d (%*d undocumented)\n" % [
451
+ num_width, @num_items, undoc_width, @undoc_items]
452
+ report << "%6.2f%% documented\n" % percent_doc
453
+ report << "\n"
454
+ report << "Elapsed: %0.1fs\n" % (Time.now - @start)
455
+
456
+ report
381
457
  end
382
458
 
383
- report
384
- end
459
+ ##
460
+ # Determines which parameters in +method+ were not documented. Returns a
461
+ # total parameter count and an Array of undocumented methods.
385
462
 
386
- ##
387
- # Returns a summary of the collected statistics.
388
-
389
- def summary
390
- calculate
391
-
392
- num_width = [@num_files, @num_items].max.to_s.length
393
- undoc_width = [
394
- @undoc_attributes,
395
- @undoc_classes,
396
- @undoc_constants,
397
- @undoc_items,
398
- @undoc_methods,
399
- @undoc_modules,
400
- @undoc_params,
401
- ].max.to_s.length
402
-
403
- report = RDoc::Markup::Verbatim.new
404
-
405
- report << "Files: %*d\n" % [num_width, @num_files]
406
-
407
- report << "\n"
408
-
409
- report << "Classes: %*d (%*d undocumented)\n" % [
410
- num_width, @num_classes, undoc_width, @undoc_classes]
411
- report << "Modules: %*d (%*d undocumented)\n" % [
412
- num_width, @num_modules, undoc_width, @undoc_modules]
413
- report << "Constants: %*d (%*d undocumented)\n" % [
414
- num_width, @num_constants, undoc_width, @undoc_constants]
415
- report << "Attributes: %*d (%*d undocumented)\n" % [
416
- num_width, @num_attributes, undoc_width, @undoc_attributes]
417
- report << "Methods: %*d (%*d undocumented)\n" % [
418
- num_width, @num_methods, undoc_width, @undoc_methods]
419
- report << "Parameters: %*d (%*d undocumented)\n" % [
420
- num_width, @num_params, undoc_width, @undoc_params] if
421
- @coverage_level > 0
422
-
423
- report << "\n"
424
-
425
- report << "Total: %*d (%*d undocumented)\n" % [
426
- num_width, @num_items, undoc_width, @undoc_items]
427
-
428
- report << "%6.2f%% documented\n" % percent_doc
429
- report << "\n"
430
- report << "Elapsed: %0.1fs\n" % (Time.now - @start)
431
-
432
- RDoc::Markup::Document.new report
433
- end
463
+ def undoc_params(method)
464
+ @formatter ||= Markup::ToTtOnly.new
434
465
 
435
- ##
436
- # Determines which parameters in +method+ were not documented. Returns a
437
- # total parameter count and an Array of undocumented methods.
466
+ params = method.param_list
438
467
 
439
- def undoc_params(method)
440
- @formatter ||= RDoc::Markup::ToTtOnly.new
468
+ params = params.map { |param| param.gsub(/^\*\*?/, '') }
441
469
 
442
- params = method.param_list
470
+ return 0, [] if params.empty?
443
471
 
444
- params = params.map { |param| param.gsub(/^\*\*?/, '') }
472
+ document = parse method.comment
445
473
 
446
- return 0, [] if params.empty?
474
+ tts = document.accept @formatter
447
475
 
448
- document = parse method.comment
476
+ undoc = params - tts
449
477
 
450
- tts = document.accept @formatter
478
+ [params.length, undoc]
479
+ end
451
480
 
452
- undoc = params - tts
481
+ autoload :Quiet, "#{__dir__}/stats/quiet"
482
+ autoload :Normal, "#{__dir__}/stats/normal"
483
+ autoload :Verbose, "#{__dir__}/stats/verbose"
453
484
 
454
- [params.length, undoc]
455
485
  end
456
-
457
- autoload :Quiet, "#{__dir__}/stats/quiet"
458
- autoload :Normal, "#{__dir__}/stats/normal"
459
- autoload :Verbose, "#{__dir__}/stats/verbose"
460
-
461
486
  end