rdoc 3.12.2 → 4.0.0.preview2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rdoc might be problematic. Click here for more details.

Files changed (200) hide show
  1. checksums.yaml +6 -6
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/.autotest +3 -2
  5. data/DEVELOPERS.rdoc +53 -0
  6. data/History.rdoc +159 -25
  7. data/LEGAL.rdoc +12 -0
  8. data/Manifest.txt +56 -3
  9. data/README.rdoc +87 -19
  10. data/Rakefile +11 -2
  11. data/TODO.rdoc +20 -13
  12. data/bin/rdoc +4 -0
  13. data/lib/gauntlet_rdoc.rb +1 -1
  14. data/lib/rdoc.rb +32 -71
  15. data/lib/rdoc/any_method.rb +75 -21
  16. data/lib/rdoc/attr.rb +49 -10
  17. data/lib/rdoc/class_module.rb +182 -32
  18. data/lib/rdoc/code_object.rb +54 -12
  19. data/lib/rdoc/comment.rb +8 -1
  20. data/lib/rdoc/constant.rb +100 -6
  21. data/lib/rdoc/context.rb +93 -41
  22. data/lib/rdoc/context/section.rb +143 -28
  23. data/lib/rdoc/cross_reference.rb +58 -50
  24. data/lib/rdoc/encoding.rb +34 -29
  25. data/lib/rdoc/erb_partial.rb +18 -0
  26. data/lib/rdoc/extend.rb +117 -0
  27. data/lib/rdoc/generator.rb +11 -6
  28. data/lib/rdoc/generator/darkfish.rb +250 -62
  29. data/lib/rdoc/generator/json_index.rb +20 -12
  30. data/lib/rdoc/generator/markup.rb +10 -12
  31. data/lib/rdoc/generator/ri.rb +7 -60
  32. data/lib/rdoc/generator/template/darkfish/_head.rhtml +7 -7
  33. data/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml +16 -0
  34. data/lib/rdoc/generator/template/darkfish/_sidebar_in_files.rhtml +1 -1
  35. data/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml +14 -0
  36. data/lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml +1 -1
  37. data/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml +13 -0
  38. data/lib/rdoc/generator/template/darkfish/class.rhtml +15 -1
  39. data/lib/rdoc/generator/template/darkfish/images/arrow_up.png +0 -0
  40. data/lib/rdoc/generator/template/darkfish/index.rhtml +3 -3
  41. data/lib/rdoc/generator/template/darkfish/js/darkfish.js +7 -9
  42. data/lib/rdoc/generator/template/darkfish/page.rhtml +2 -0
  43. data/lib/rdoc/generator/template/darkfish/rdoc.css +31 -0
  44. data/lib/rdoc/generator/template/darkfish/servlet_not_found.rhtml +18 -0
  45. data/lib/rdoc/generator/template/darkfish/servlet_root.rhtml +37 -0
  46. data/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml +3 -3
  47. data/lib/rdoc/include.rb +12 -3
  48. data/lib/rdoc/markdown.kpeg +1186 -0
  49. data/lib/rdoc/markdown.rb +16336 -0
  50. data/lib/rdoc/markdown/entities.rb +2128 -0
  51. data/lib/rdoc/markdown/literals_1_8.kpeg +18 -0
  52. data/lib/rdoc/markdown/literals_1_8.rb +454 -0
  53. data/lib/rdoc/markdown/literals_1_9.kpeg +22 -0
  54. data/lib/rdoc/markdown/literals_1_9.rb +417 -0
  55. data/lib/rdoc/markup.rb +69 -10
  56. data/lib/rdoc/markup/attr_changer.rb +2 -5
  57. data/lib/rdoc/markup/attribute_manager.rb +23 -14
  58. data/lib/rdoc/markup/attributes.rb +70 -0
  59. data/lib/rdoc/markup/block_quote.rb +14 -0
  60. data/lib/rdoc/markup/document.rb +20 -4
  61. data/lib/rdoc/markup/formatter.rb +17 -6
  62. data/lib/rdoc/markup/formatter_test_case.rb +93 -24
  63. data/lib/rdoc/markup/hard_break.rb +31 -0
  64. data/lib/rdoc/markup/heading.rb +1 -1
  65. data/lib/rdoc/markup/indented_paragraph.rb +14 -0
  66. data/lib/rdoc/markup/list.rb +23 -4
  67. data/lib/rdoc/markup/list_item.rb +17 -4
  68. data/lib/rdoc/markup/paragraph.rb +14 -0
  69. data/lib/rdoc/markup/parser.rb +107 -60
  70. data/lib/rdoc/markup/raw.rb +4 -4
  71. data/lib/rdoc/markup/special.rb +3 -3
  72. data/lib/rdoc/markup/to_ansi.rb +7 -1
  73. data/lib/rdoc/markup/to_html.rb +42 -14
  74. data/lib/rdoc/markup/to_html_crossref.rb +10 -9
  75. data/lib/rdoc/markup/to_html_snippet.rb +20 -4
  76. data/lib/rdoc/markup/to_joined_paragraph.rb +68 -0
  77. data/lib/rdoc/markup/to_label.rb +20 -1
  78. data/lib/rdoc/markup/to_markdown.rb +134 -0
  79. data/lib/rdoc/markup/to_rdoc.rb +36 -5
  80. data/lib/rdoc/markup/to_table_of_contents.rb +6 -1
  81. data/lib/rdoc/markup/to_tt_only.rb +11 -2
  82. data/lib/rdoc/markup/verbatim.rb +19 -0
  83. data/lib/rdoc/method_attr.rb +33 -19
  84. data/lib/rdoc/normal_class.rb +26 -7
  85. data/lib/rdoc/normal_module.rb +10 -5
  86. data/lib/rdoc/options.rb +95 -21
  87. data/lib/rdoc/parser.rb +6 -2
  88. data/lib/rdoc/parser/c.rb +212 -97
  89. data/lib/rdoc/parser/markdown.rb +23 -0
  90. data/lib/rdoc/parser/ruby.rb +115 -35
  91. data/lib/rdoc/parser/ruby_tools.rb +8 -3
  92. data/lib/rdoc/rd.rb +8 -4
  93. data/lib/rdoc/rd/block_parser.rb +1 -1
  94. data/lib/rdoc/rd/block_parser.ry +1 -1
  95. data/lib/rdoc/rdoc.rb +45 -21
  96. data/lib/rdoc/ri/driver.rb +322 -76
  97. data/lib/rdoc/ri/paths.rb +90 -31
  98. data/lib/rdoc/ri/store.rb +2 -353
  99. data/lib/rdoc/ruby_lex.rb +5 -21
  100. data/lib/rdoc/ruby_token.rb +2 -3
  101. data/lib/rdoc/rubygems_hook.rb +21 -9
  102. data/lib/rdoc/servlet.rb +302 -0
  103. data/lib/rdoc/stats.rb +28 -20
  104. data/lib/rdoc/store.rb +881 -0
  105. data/lib/rdoc/task.rb +2 -1
  106. data/lib/rdoc/test_case.rb +103 -1
  107. data/lib/rdoc/text.rb +5 -4
  108. data/lib/rdoc/tom_doc.rb +17 -16
  109. data/lib/rdoc/top_level.rb +43 -285
  110. data/test/MarkdownTest_1.0.3/Amps and angle encoding.text +21 -0
  111. data/test/MarkdownTest_1.0.3/Auto links.text +13 -0
  112. data/test/MarkdownTest_1.0.3/Backslash escapes.text +120 -0
  113. data/test/MarkdownTest_1.0.3/Blockquotes with code blocks.text +11 -0
  114. data/test/MarkdownTest_1.0.3/Code Blocks.text +14 -0
  115. data/test/MarkdownTest_1.0.3/Code Spans.text +6 -0
  116. data/test/MarkdownTest_1.0.3/Hard-wrapped paragraphs with list-like lines.text +8 -0
  117. data/test/MarkdownTest_1.0.3/Horizontal rules.text +67 -0
  118. data/test/MarkdownTest_1.0.3/Inline HTML (Advanced).text +15 -0
  119. data/test/MarkdownTest_1.0.3/Inline HTML (Simple).text +69 -0
  120. data/test/MarkdownTest_1.0.3/Inline HTML comments.text +13 -0
  121. data/test/MarkdownTest_1.0.3/Links, inline style.text +12 -0
  122. data/test/MarkdownTest_1.0.3/Links, reference style.text +71 -0
  123. data/test/MarkdownTest_1.0.3/Links, shortcut references.text +20 -0
  124. data/test/MarkdownTest_1.0.3/Literal quotes in titles.text +7 -0
  125. data/test/MarkdownTest_1.0.3/Markdown Documentation - Basics.text +306 -0
  126. data/test/MarkdownTest_1.0.3/Markdown Documentation - Syntax.text +888 -0
  127. data/test/MarkdownTest_1.0.3/Nested blockquotes.text +5 -0
  128. data/test/MarkdownTest_1.0.3/Ordered and unordered lists.text +131 -0
  129. data/test/MarkdownTest_1.0.3/Strong and em together.text +7 -0
  130. data/test/MarkdownTest_1.0.3/Tabs.text +21 -0
  131. data/test/MarkdownTest_1.0.3/Tidyness.text +5 -0
  132. data/test/test_attribute_manager.rb +7 -4
  133. data/test/test_rdoc_any_method.rb +84 -13
  134. data/test/test_rdoc_attr.rb +59 -9
  135. data/test/test_rdoc_class_module.rb +670 -73
  136. data/test/test_rdoc_code_object.rb +21 -1
  137. data/test/test_rdoc_comment.rb +1 -1
  138. data/test/test_rdoc_constant.rb +132 -0
  139. data/test/test_rdoc_context.rb +84 -18
  140. data/test/test_rdoc_context_section.rb +99 -15
  141. data/test/test_rdoc_cross_reference.rb +1 -1
  142. data/test/test_rdoc_encoding.rb +17 -1
  143. data/test/test_rdoc_extend.rb +94 -0
  144. data/test/test_rdoc_generator_darkfish.rb +45 -19
  145. data/test/test_rdoc_generator_json_index.rb +27 -7
  146. data/test/test_rdoc_generator_markup.rb +3 -3
  147. data/test/test_rdoc_generator_ri.rb +11 -9
  148. data/test/test_rdoc_include.rb +12 -0
  149. data/test/test_rdoc_markdown.rb +977 -0
  150. data/test/test_rdoc_markdown_test.rb +1891 -0
  151. data/test/test_rdoc_markup.rb +1 -1
  152. data/test/test_rdoc_markup_attribute_manager.rb +2 -2
  153. data/test/test_rdoc_markup_attributes.rb +39 -0
  154. data/test/test_rdoc_markup_document.rb +16 -1
  155. data/test/test_rdoc_markup_formatter.rb +7 -4
  156. data/test/test_rdoc_markup_hard_break.rb +31 -0
  157. data/test/test_rdoc_markup_indented_paragraph.rb +14 -0
  158. data/test/test_rdoc_markup_paragraph.rb +15 -1
  159. data/test/test_rdoc_markup_parser.rb +152 -89
  160. data/test/test_rdoc_markup_to_ansi.rb +23 -2
  161. data/test/test_rdoc_markup_to_bs.rb +24 -0
  162. data/test/test_rdoc_markup_to_html.rb +50 -19
  163. data/test/test_rdoc_markup_to_html_crossref.rb +23 -5
  164. data/test/test_rdoc_markup_to_html_snippet.rb +49 -8
  165. data/test/test_rdoc_markup_to_joined_paragraph.rb +32 -0
  166. data/test/test_rdoc_markup_to_label.rb +63 -1
  167. data/test/test_rdoc_markup_to_markdown.rb +352 -0
  168. data/test/test_rdoc_markup_to_rdoc.rb +22 -2
  169. data/test/test_rdoc_markup_to_table_of_contents.rb +44 -39
  170. data/test/test_rdoc_markup_to_tt_only.rb +20 -0
  171. data/test/test_rdoc_markup_verbatim.rb +13 -0
  172. data/test/test_rdoc_method_attr.rb +5 -0
  173. data/test/test_rdoc_normal_class.rb +24 -5
  174. data/test/test_rdoc_normal_module.rb +1 -1
  175. data/test/test_rdoc_options.rb +21 -6
  176. data/test/test_rdoc_parser.rb +24 -0
  177. data/test/test_rdoc_parser_c.rb +151 -26
  178. data/test/test_rdoc_parser_markdown.rb +55 -0
  179. data/test/test_rdoc_parser_rd.rb +2 -2
  180. data/test/test_rdoc_parser_ruby.rb +468 -109
  181. data/test/test_rdoc_parser_simple.rb +2 -2
  182. data/test/test_rdoc_rd_block_parser.rb +0 -4
  183. data/test/test_rdoc_rdoc.rb +110 -22
  184. data/test/test_rdoc_ri_driver.rb +415 -80
  185. data/test/test_rdoc_ri_paths.rb +122 -13
  186. data/test/test_rdoc_ruby_lex.rb +5 -61
  187. data/test/test_rdoc_ruby_token.rb +19 -0
  188. data/test/test_rdoc_rubygems_hook.rb +64 -43
  189. data/test/test_rdoc_servlet.rb +429 -0
  190. data/test/test_rdoc_stats.rb +83 -24
  191. data/test/{test_rdoc_ri_store.rb → test_rdoc_store.rb} +395 -22
  192. data/test/test_rdoc_task.rb +2 -2
  193. data/test/test_rdoc_text.rb +37 -11
  194. data/test/test_rdoc_tom_doc.rb +59 -62
  195. data/test/test_rdoc_top_level.rb +71 -113
  196. data/test/xref_test_case.rb +7 -9
  197. metadata +122 -39
  198. metadata.gz.sig +0 -0
  199. data/CVE-2013-0256.rdoc +0 -49
  200. data/lib/rdoc/markup/attribute.rb +0 -51
@@ -23,17 +23,18 @@ class RDoc::Stats
23
23
  # Creates a new Stats that will have +num_files+. +verbosity+ defaults to 1
24
24
  # which will create an RDoc::Stats::Normal outputter.
25
25
 
26
- def initialize num_files, verbosity = 1
27
- @files_so_far = 0
26
+ def initialize store, num_files, verbosity = 1
28
27
  @num_files = num_files
28
+ @store = store
29
29
 
30
- @coverage_level = 0
31
- @doc_items = nil
30
+ @coverage_level = 0
31
+ @doc_items = nil
32
+ @files_so_far = 0
32
33
  @fully_documented = false
33
- @num_params = 0
34
- @percent_doc = nil
35
- @start = Time.now
36
- @undoc_params = 0
34
+ @num_params = 0
35
+ @percent_doc = nil
36
+ @start = Time.now
37
+ @undoc_params = 0
37
38
 
38
39
  @display = case verbosity
39
40
  when 0 then Quiet.new num_files
@@ -106,7 +107,10 @@ class RDoc::Stats
106
107
  def calculate
107
108
  return if @doc_items
108
109
 
109
- ucm = RDoc::TopLevel.unique_classes_and_modules
110
+ ucm = @store.unique_classes_and_modules
111
+
112
+ classes = @store.unique_classes.reject { |cm| cm.full_name == 'Object' }
113
+
110
114
  constants = []
111
115
  ucm.each { |cm| constants.concat cm.constants }
112
116
 
@@ -117,10 +121,10 @@ class RDoc::Stats
117
121
  ucm.each { |cm| attributes.concat cm.attributes }
118
122
 
119
123
  @num_attributes, @undoc_attributes = doc_stats attributes
120
- @num_classes, @undoc_classes = doc_stats RDoc::TopLevel.unique_classes
124
+ @num_classes, @undoc_classes = doc_stats classes
121
125
  @num_constants, @undoc_constants = doc_stats constants
122
126
  @num_methods, @undoc_methods = doc_stats methods
123
- @num_modules, @undoc_modules = doc_stats RDoc::TopLevel.unique_modules
127
+ @num_modules, @undoc_modules = doc_stats @store.unique_modules
124
128
 
125
129
  @num_items =
126
130
  @num_attributes +
@@ -221,7 +225,7 @@ class RDoc::Stats
221
225
  return great_job if @num_items == @doc_items
222
226
  end
223
227
 
224
- ucm = RDoc::TopLevel.unique_classes_and_modules
228
+ ucm = @store.unique_classes_and_modules
225
229
 
226
230
  ucm.sort.each do |cm|
227
231
  report << report_class_module(cm) {
@@ -255,8 +259,8 @@ class RDoc::Stats
255
259
 
256
260
  cm.each_attribute do |attr|
257
261
  next if attr.documented?
258
- report << " #{attr.definition} :#{attr.name} " \
259
- "# in file #{attr.file.full_name}"
262
+ line = attr.line ? ":#{attr.line}" : nil
263
+ report << " #{attr.definition} :#{attr.name} # in file #{attr.file.full_name}#{line}"
260
264
  end
261
265
 
262
266
  report
@@ -273,9 +277,8 @@ class RDoc::Stats
273
277
 
274
278
  if cm.in_files.empty? then
275
279
  report << "# #{cm.definition} is referenced but empty."
276
- report << '#'
277
- report << '# It probably came from another project. ' \
278
- "I'm sorry I'm holding it against you."
280
+ report << "#"
281
+ report << "# It probably came from another project. I'm sorry I'm holding it against you."
279
282
  report << nil
280
283
 
281
284
  return report
@@ -318,7 +321,9 @@ class RDoc::Stats
318
321
  # TODO constant aliases are listed in the summary but not reported
319
322
  # figure out what to do here
320
323
  next if constant.documented? || constant.is_alias_for
321
- report << " # in file #{constant.file.full_name}"
324
+
325
+ line = constant.line ? ":#{constant.line}" : line
326
+ report << " # in file #{constant.file.full_name}#{line}"
322
327
  report << " #{constant.name} = nil"
323
328
  end
324
329
 
@@ -350,9 +355,12 @@ class RDoc::Stats
350
355
  end
351
356
 
352
357
  next if method.documented? and not param_report
353
- report << " # in file #{method.file.full_name}"
354
- report << param_report if param_report
358
+
359
+ line = method.line ? ":#{method.line}" : nil
355
360
  scope = method.singleton ? 'self.' : nil
361
+
362
+ report << " # in file #{method.file.full_name}#{line}"
363
+ report << param_report if param_report
356
364
  report << " def #{scope}#{method.name}#{method.params}; end"
357
365
  report << nil
358
366
  end
@@ -0,0 +1,881 @@
1
+ require 'fileutils'
2
+
3
+ ##
4
+ # A set of rdoc data for a single project (gem, path, etc.).
5
+ #
6
+ # The store manages reading and writing ri data for a project and maintains a
7
+ # cache of methods, classes and ancestors in the store.
8
+ #
9
+ # The store maintains a #cache of its contents for faster lookup. After
10
+ # adding items to the store it must be flushed using #save_cache. The cache
11
+ # contains the following structures:
12
+ #
13
+ # @cache = {
14
+ # :ancestors => {}, # class name => ancestor names
15
+ # :attributes => {}, # class name => attributes
16
+ # :class_methods => {}, # class name => class methods
17
+ # :instance_methods => {}, # class name => instance methods
18
+ # :modules => [], # classes and modules in this store
19
+ # :pages => [], # page names
20
+ # }
21
+ #--
22
+ # TODO need to prune classes
23
+
24
+ class RDoc::Store
25
+
26
+ ##
27
+ # Errors raised from loading or saving the store
28
+
29
+ class Error < RDoc::Error
30
+ end
31
+
32
+ ##
33
+ # Raised when a stored file for a class, module, page or method is missing.
34
+
35
+ class MissingFileError < Error
36
+
37
+ ##
38
+ # The store the file should exist in
39
+
40
+ attr_reader :store
41
+
42
+ ##
43
+ # The file the #name should be saved as
44
+
45
+ attr_reader :file
46
+
47
+ ##
48
+ # The name of the object the #file would be loaded from
49
+
50
+ attr_reader :name
51
+
52
+ ##
53
+ # Creates a new MissingFileError for the missing +file+ for the given
54
+ # +name+ that should have been in the +store+.
55
+
56
+ def initialize store, file, name
57
+ @store = store
58
+ @file = file
59
+ @name = name
60
+ end
61
+
62
+ def message
63
+ "store at #{@store.path} missing file #{@file} for #{@name}"
64
+ end
65
+
66
+ end
67
+
68
+ ##
69
+ # Stores the name of the C variable a class belongs to. This helps wire up
70
+ # classes defined from C across files.
71
+
72
+ attr_reader :c_enclosure_classes
73
+
74
+ ##
75
+ # If true this Store will not write any files
76
+
77
+ attr_accessor :dry_run
78
+
79
+ ##
80
+ # Path this store reads or writes
81
+
82
+ attr_accessor :path
83
+
84
+ ##
85
+ # The RDoc::RDoc driver for this parse tree. This allows classes consulting
86
+ # the documentation tree to access user-set options, for example.
87
+
88
+ attr_accessor :rdoc
89
+
90
+ ##
91
+ # Type of ri datastore this was loaded from. See RDoc::RI::Driver,
92
+ # RDoc::RI::Paths.
93
+
94
+ attr_accessor :type
95
+
96
+ ##
97
+ # The contents of the Store
98
+
99
+ attr_reader :cache
100
+
101
+ ##
102
+ # The encoding of the contents in the Store
103
+
104
+ attr_accessor :encoding
105
+
106
+ ##
107
+ # Creates a new Store of +type+ that will load or save to +path+
108
+
109
+ def initialize path = nil, type = nil
110
+ @dry_run = false
111
+ @encoding = nil
112
+ @path = path
113
+ @rdoc = nil
114
+ @type = type
115
+
116
+ @cache = {
117
+ :ancestors => {},
118
+ :attributes => {},
119
+ :class_methods => {},
120
+ :encoding => @encoding,
121
+ :instance_methods => {},
122
+ :main => nil,
123
+ :modules => [],
124
+ :pages => [],
125
+ :title => nil,
126
+ }
127
+
128
+ @classes_hash = {}
129
+ @modules_hash = {}
130
+ @files_hash = {}
131
+
132
+ @c_enclosure_classes = {}
133
+
134
+ @unique_classes = nil
135
+ @unique_modules = nil
136
+ end
137
+
138
+ ##
139
+ # Adds the file with +name+ as an RDoc::TopLevel to the store. Returns the
140
+ # created RDoc::TopLevel.
141
+
142
+ def add_file absolute_name, relative_name = absolute_name
143
+ unless top_level = @files_hash[relative_name] then
144
+ top_level = RDoc::TopLevel.new absolute_name, relative_name
145
+ top_level.store = self
146
+ @files_hash[relative_name] = top_level
147
+ end
148
+
149
+ top_level
150
+ end
151
+
152
+ ##
153
+ # Returns all classes discovered by RDoc
154
+
155
+ def all_classes
156
+ @classes_hash.values
157
+ end
158
+
159
+ ##
160
+ # Returns all classes and modules discovered by RDoc
161
+
162
+ def all_classes_and_modules
163
+ @classes_hash.values + @modules_hash.values
164
+ end
165
+
166
+ ##
167
+ # All TopLevels known to RDoc
168
+
169
+ def all_files
170
+ @files_hash.values
171
+ end
172
+
173
+ ##
174
+ # Returns all modules discovered by RDoc
175
+
176
+ def all_modules
177
+ modules_hash.values
178
+ end
179
+
180
+ ##
181
+ # Ancestors cache accessor. Maps a klass name to an Array of its ancestors
182
+ # in this store. If Foo in this store inherits from Object, Kernel won't be
183
+ # listed (it will be included from ruby's ri store).
184
+
185
+ def ancestors
186
+ @cache[:ancestors]
187
+ end
188
+
189
+ ##
190
+ # Attributes cache accessor. Maps a class to an Array of its attributes.
191
+
192
+ def attributes
193
+ @cache[:attributes]
194
+ end
195
+
196
+ ##
197
+ # Path to the cache file
198
+
199
+ def cache_path
200
+ File.join @path, 'cache.ri'
201
+ end
202
+
203
+ ##
204
+ # Path to the ri data for +klass_name+
205
+
206
+ def class_file klass_name
207
+ name = klass_name.split('::').last
208
+ File.join class_path(klass_name), "cdesc-#{name}.ri"
209
+ end
210
+
211
+ ##
212
+ # Class methods cache accessor. Maps a class to an Array of its class
213
+ # methods (not full name).
214
+
215
+ def class_methods
216
+ @cache[:class_methods]
217
+ end
218
+
219
+ ##
220
+ # Path where data for +klass_name+ will be stored (methods or class data)
221
+
222
+ def class_path klass_name
223
+ File.join @path, *klass_name.split('::')
224
+ end
225
+
226
+ ##
227
+ # Hash of all classes known to RDoc
228
+
229
+ def classes_hash
230
+ @classes_hash
231
+ end
232
+
233
+ ##
234
+ # Removes empty items and ensures item in each collection are unique and
235
+ # sorted
236
+
237
+ def clean_cache_collection collection # :nodoc:
238
+ collection.each do |name, item|
239
+ if item.empty? then
240
+ collection.delete name
241
+ else
242
+ # HACK mongrel-1.1.5 documents its files twice
243
+ item.uniq!
244
+ item.sort!
245
+ end
246
+ end
247
+ end
248
+
249
+ ##
250
+ # Prepares the RDoc code object tree for use by a generator.
251
+ #
252
+ # It finds unique classes/modules defined, and replaces classes/modules that
253
+ # are aliases for another one by a copy with RDoc::ClassModule#is_alias_for
254
+ # set.
255
+ #
256
+ # It updates the RDoc::ClassModule#constant_aliases attribute of "real"
257
+ # classes or modules.
258
+ #
259
+ # It also completely removes the classes and modules that should be removed
260
+ # from the documentation and the methods that have a visibility below
261
+ # +min_visibility+, which is the <tt>--visibility</tt> option.
262
+ #
263
+ # See also RDoc::Context#remove_from_documentation?
264
+
265
+ def complete min_visibility
266
+ fix_basic_object_inheritance
267
+
268
+ # cache included modules before they are removed from the documentation
269
+ all_classes_and_modules.each { |cm| cm.ancestors }
270
+
271
+ remove_nodoc @classes_hash
272
+ remove_nodoc @modules_hash
273
+
274
+ @unique_classes = find_unique @classes_hash
275
+ @unique_modules = find_unique @modules_hash
276
+
277
+ unique_classes_and_modules.each do |cm|
278
+ cm.complete min_visibility
279
+ end
280
+
281
+ @files_hash.each_key do |file_name|
282
+ tl = @files_hash[file_name]
283
+
284
+ unless tl.text? then
285
+ tl.modules_hash.clear
286
+ tl.classes_hash.clear
287
+
288
+ tl.classes_or_modules.each do |cm|
289
+ name = cm.full_name
290
+ if cm.type == 'class' then
291
+ tl.classes_hash[name] = cm if @classes_hash[name]
292
+ else
293
+ tl.modules_hash[name] = cm if @modules_hash[name]
294
+ end
295
+ end
296
+ end
297
+ end
298
+ end
299
+
300
+ ##
301
+ # Hash of all files known to RDoc
302
+
303
+ def files_hash
304
+ @files_hash
305
+ end
306
+
307
+ ##
308
+ # Finds the class with +name+ in all discovered classes
309
+
310
+ def find_class_named name
311
+ @classes_hash[name]
312
+ end
313
+
314
+ ##
315
+ # Finds the class with +name+ starting in namespace +from+
316
+
317
+ def find_class_named_from name, from
318
+ from = find_class_named from unless RDoc::Context === from
319
+
320
+ until RDoc::TopLevel === from do
321
+ return nil unless from
322
+
323
+ klass = from.find_class_named name
324
+ return klass if klass
325
+
326
+ from = from.parent
327
+ end
328
+
329
+ find_class_named name
330
+ end
331
+
332
+ ##
333
+ # Finds the class or module with +name+
334
+
335
+ def find_class_or_module name
336
+ name = $' if name =~ /^::/
337
+ @classes_hash[name] || @modules_hash[name]
338
+ end
339
+
340
+ ##
341
+ # Finds the file with +name+ in all discovered files
342
+
343
+ def find_file_named name
344
+ @files_hash[name]
345
+ end
346
+
347
+ ##
348
+ # Finds the module with +name+ in all discovered modules
349
+
350
+ def find_module_named name
351
+ @modules_hash[name]
352
+ end
353
+
354
+ ##
355
+ # Returns the RDoc::TopLevel that is a text file and has the given
356
+ # +file_name+
357
+
358
+ def find_text_page file_name
359
+ @files_hash.each_value.find do |file|
360
+ file.text? and file.full_name == file_name
361
+ end
362
+ end
363
+
364
+ ##
365
+ # Finds unique classes/modules defined in +all_hash+,
366
+ # and returns them as an array. Performs the alias
367
+ # updates in +all_hash+: see ::complete.
368
+ #--
369
+ # TODO aliases should be registered by Context#add_module_alias
370
+
371
+ def find_unique all_hash
372
+ unique = []
373
+
374
+ all_hash.each_pair do |full_name, cm|
375
+ unique << cm if full_name == cm.full_name
376
+ end
377
+
378
+ unique
379
+ end
380
+
381
+ ##
382
+ # Fixes the erroneous <tt>BasicObject < Object</tt> in 1.9.
383
+ #
384
+ # Because we assumed all classes without a stated superclass
385
+ # inherit from Object, we have the above wrong inheritance.
386
+ #
387
+ # We fix BasicObject right away if we are running in a Ruby
388
+ # version >= 1.9. If not, we may be documenting 1.9 source
389
+ # while running under 1.8: we search the files of BasicObject
390
+ # for "object.c", and fix the inheritance if we find it.
391
+
392
+ def fix_basic_object_inheritance
393
+ basic = classes_hash['BasicObject']
394
+ return unless basic
395
+ if RUBY_VERSION >= '1.9'
396
+ basic.superclass = nil
397
+ elsif basic.in_files.any? { |f| File.basename(f.full_name) == 'object.c' }
398
+ basic.superclass = nil
399
+ end
400
+ end
401
+
402
+ ##
403
+ # Friendly rendition of #path
404
+
405
+ def friendly_path
406
+ case type
407
+ when :gem then
408
+ parent = File.expand_path '..', @path
409
+ "gem #{File.basename parent}"
410
+ when :home then '~/.rdoc'
411
+ when :site then 'ruby site'
412
+ when :system then 'ruby core'
413
+ else @path
414
+ end
415
+ end
416
+
417
+ def inspect # :nodoc:
418
+ "#<%s:0x%x %s %p>" % [self.class, object_id, @path, module_names.sort]
419
+ end
420
+
421
+ ##
422
+ # Instance methods cache accessor. Maps a class to an Array of its
423
+ # instance methods (not full name).
424
+
425
+ def instance_methods
426
+ @cache[:instance_methods]
427
+ end
428
+
429
+ ##
430
+ # Loads all items from this store into memory. This recreates a
431
+ # documentation tree for use by a generator
432
+
433
+ def load_all
434
+ load_cache
435
+
436
+ module_names.each do |module_name|
437
+ mod = find_class_or_module(module_name) || load_class(module_name)
438
+
439
+ # load method documentation since the loaded class/module does not have
440
+ # it
441
+ loaded_methods = mod.method_list.map do |method|
442
+ load_method module_name, method.full_name
443
+ end
444
+
445
+ mod.method_list.replace loaded_methods
446
+
447
+ loaded_attributes = mod.attributes.map do |attribute|
448
+ load_method module_name, attribute.full_name
449
+ end
450
+
451
+ mod.attributes.replace loaded_attributes
452
+ end
453
+
454
+ all_classes_and_modules.each do |mod|
455
+ descendent_re = /^#{mod.full_name}::[^:]+$/
456
+
457
+ module_names.each do |name|
458
+ next unless name =~ descendent_re
459
+
460
+ descendent = find_class_or_module name
461
+
462
+ case descendent
463
+ when RDoc::NormalClass then
464
+ mod.classes_hash[name] = descendent
465
+ when RDoc::NormalModule then
466
+ mod.modules_hash[name] = descendent
467
+ end
468
+ end
469
+ end
470
+
471
+ @cache[:pages].each do |page_name|
472
+ page = load_page page_name
473
+ @files_hash[page_name] = page
474
+ end
475
+ end
476
+
477
+ ##
478
+ # Loads cache file for this store
479
+
480
+ def load_cache
481
+ #orig_enc = @encoding
482
+
483
+ open cache_path, 'rb' do |io|
484
+ @cache = Marshal.load io.read
485
+ end
486
+
487
+ load_enc = @cache[:encoding]
488
+
489
+ # TODO this feature will be time-consuming to add:
490
+ # a) Encodings may be incompatible but transcodeable
491
+ # b) Need to warn in the appropriate spots, wherever they may be
492
+ # c) Need to handle cross-cache differences in encodings
493
+ # d) Need to warn when generating into a cache with different encodings
494
+ #
495
+ #if orig_enc and load_enc != orig_enc then
496
+ # warn "Cached encoding #{load_enc} is incompatible with #{orig_enc}\n" \
497
+ # "from #{path}/cache.ri" unless
498
+ # Encoding.compatible? orig_enc, load_enc
499
+ #end
500
+
501
+ @encoding = load_enc unless @encoding
502
+
503
+ @cache[:pages] ||= []
504
+ @cache[:main] ||= nil
505
+
506
+ @cache
507
+ rescue Errno::ENOENT
508
+ end
509
+
510
+ ##
511
+ # Loads ri data for +klass_name+
512
+
513
+ def load_class klass_name
514
+ file = class_file klass_name
515
+
516
+ obj = open file, 'rb' do |io|
517
+ Marshal.load io.read
518
+ end
519
+
520
+ obj.store = self
521
+
522
+ case obj
523
+ when RDoc::NormalClass then
524
+ @classes_hash[klass_name] = obj
525
+ when RDoc::NormalModule then
526
+ @modules_hash[klass_name] = obj
527
+ end
528
+ rescue Errno::ENOENT => e
529
+ error = MissingFileError.new(self, file, klass_name)
530
+ error.set_backtrace e.backtrace
531
+ raise error
532
+ end
533
+
534
+ ##
535
+ # Loads ri data for +method_name+ in +klass_name+
536
+
537
+ def load_method klass_name, method_name
538
+ file = method_file klass_name, method_name
539
+
540
+ open file, 'rb' do |io|
541
+ obj = Marshal.load io.read
542
+ obj.store = self
543
+ obj.parent =
544
+ find_class_or_module(klass_name) || load_class(klass_name) unless
545
+ obj.parent
546
+ obj
547
+ end
548
+ rescue Errno::ENOENT => e
549
+ error = MissingFileError.new(self, file, klass_name + method_name)
550
+ error.set_backtrace e.backtrace
551
+ raise error
552
+ end
553
+
554
+ ##
555
+ # Loads ri data for +page_name+
556
+
557
+ def load_page page_name
558
+ file = page_file page_name
559
+
560
+ open file, 'rb' do |io|
561
+ obj = Marshal.load io.read
562
+ obj.store = self
563
+ obj
564
+ end
565
+ rescue Errno::ENOENT => e
566
+ error = MissingFileError.new(self, file, page_name)
567
+ error.set_backtrace e.backtrace
568
+ raise error
569
+ end
570
+
571
+ ##
572
+ # Gets the main page for this RDoc store. This page is used as the root of
573
+ # the RDoc server.
574
+
575
+ def main
576
+ @cache[:main]
577
+ end
578
+
579
+ ##
580
+ # Sets the main page for this RDoc store.
581
+
582
+ def main= page
583
+ @cache[:main] = page
584
+ end
585
+
586
+ ##
587
+ # Path to the ri data for +method_name+ in +klass_name+
588
+
589
+ def method_file klass_name, method_name
590
+ method_name = method_name.split('::').last
591
+ method_name =~ /#(.*)/
592
+ method_type = $1 ? 'i' : 'c'
593
+ method_name = $1 if $1
594
+
595
+ method_name = if ''.respond_to? :ord then
596
+ method_name.gsub(/\W/) { "%%%02x" % $&[0].ord }
597
+ else
598
+ method_name.gsub(/\W/) { "%%%02x" % $&[0] }
599
+ end
600
+
601
+ File.join class_path(klass_name), "#{method_name}-#{method_type}.ri"
602
+ end
603
+
604
+ ##
605
+ # Modules cache accessor. An Array of all the module (and class) names in
606
+ # the store.
607
+
608
+ def module_names
609
+ @cache[:modules]
610
+ end
611
+
612
+ ##
613
+ # Hash of all modules known to RDoc
614
+
615
+ def modules_hash
616
+ @modules_hash
617
+ end
618
+
619
+ ##
620
+ # Returns the RDoc::TopLevel that is a text file and has the given +name+
621
+
622
+ def page name
623
+ @files_hash.each_value.find do |file|
624
+ file.text? and file.page_name == name
625
+ end
626
+ end
627
+
628
+ ##
629
+ # Path to the ri data for +page_name+
630
+
631
+ def page_file page_name
632
+ file_name = File.basename(page_name).gsub('.', '_')
633
+
634
+ File.join @path, File.dirname(page_name), "page-#{file_name}.ri"
635
+ end
636
+
637
+ ##
638
+ # Removes from +all_hash+ the contexts that are nodoc or have no content.
639
+ #
640
+ # See RDoc::Context#remove_from_documentation?
641
+
642
+ def remove_nodoc all_hash
643
+ all_hash.keys.each do |name|
644
+ context = all_hash[name]
645
+ all_hash.delete(name) if context.remove_from_documentation?
646
+ end
647
+ end
648
+
649
+ ##
650
+ # Saves all entries in the store
651
+
652
+ def save
653
+ load_cache
654
+
655
+ all_classes_and_modules.each do |klass|
656
+ save_class klass
657
+
658
+ klass.each_method do |method|
659
+ save_method klass, method
660
+ end
661
+
662
+ klass.each_attribute do |attribute|
663
+ save_method klass, attribute
664
+ end
665
+ end
666
+
667
+ all_files.each do |file|
668
+ save_page file
669
+ end
670
+
671
+ save_cache
672
+ end
673
+
674
+ ##
675
+ # Writes the cache file for this store
676
+
677
+ def save_cache
678
+ clean_cache_collection @cache[:ancestors]
679
+ clean_cache_collection @cache[:attributes]
680
+ clean_cache_collection @cache[:class_methods]
681
+ clean_cache_collection @cache[:instance_methods]
682
+
683
+ @cache[:modules].uniq!
684
+ @cache[:modules].sort!
685
+
686
+ @cache[:pages].uniq!
687
+ @cache[:pages].sort!
688
+
689
+ @cache[:encoding] = @encoding # this gets set twice due to assert_cache
690
+
691
+ return if @dry_run
692
+
693
+ marshal = Marshal.dump @cache
694
+
695
+ open cache_path, 'wb' do |io|
696
+ io.write marshal
697
+ end
698
+ end
699
+
700
+ ##
701
+ # Writes the ri data for +klass+ (or module)
702
+
703
+ def save_class klass
704
+ full_name = klass.full_name
705
+
706
+ FileUtils.mkdir_p class_path(full_name) unless @dry_run
707
+
708
+ @cache[:modules] << full_name
709
+
710
+ path = class_file full_name
711
+
712
+ begin
713
+ disk_klass = load_class full_name
714
+
715
+ klass = disk_klass.merge klass
716
+ rescue MissingFileError
717
+ end
718
+
719
+ # BasicObject has no ancestors
720
+ ancestors = klass.direct_ancestors.compact.map do |ancestor|
721
+ # HACK for classes we don't know about (class X < RuntimeError)
722
+ String === ancestor ? ancestor : ancestor.full_name
723
+ end
724
+
725
+ @cache[:ancestors][full_name] ||= []
726
+ @cache[:ancestors][full_name].concat ancestors
727
+
728
+ attributes = klass.attributes.map do |attribute|
729
+ "#{attribute.definition} #{attribute.name}"
730
+ end
731
+
732
+ unless attributes.empty? then
733
+ @cache[:attributes][full_name] ||= []
734
+ @cache[:attributes][full_name].concat attributes
735
+ end
736
+
737
+ to_delete = []
738
+
739
+ unless klass.method_list.empty? then
740
+ @cache[:class_methods][full_name] ||= []
741
+ @cache[:instance_methods][full_name] ||= []
742
+
743
+ class_methods, instance_methods =
744
+ klass.method_list.partition { |meth| meth.singleton }
745
+
746
+ class_methods = class_methods. map { |method| method.name }
747
+ instance_methods = instance_methods.map { |method| method.name }
748
+
749
+ old = @cache[:class_methods][full_name] - class_methods
750
+ to_delete.concat old.map { |method|
751
+ method_file full_name, "#{full_name}::#{method}"
752
+ }
753
+
754
+ old = @cache[:instance_methods][full_name] - instance_methods
755
+ to_delete.concat old.map { |method|
756
+ method_file full_name, "#{full_name}##{method}"
757
+ }
758
+
759
+ @cache[:class_methods][full_name] = class_methods
760
+ @cache[:instance_methods][full_name] = instance_methods
761
+ end
762
+
763
+ return if @dry_run
764
+
765
+ FileUtils.rm_f to_delete
766
+
767
+ marshal = Marshal.dump klass
768
+
769
+ open path, 'wb' do |io|
770
+ io.write marshal
771
+ end
772
+ end
773
+
774
+ ##
775
+ # Writes the ri data for +method+ on +klass+
776
+
777
+ def save_method klass, method
778
+ full_name = klass.full_name
779
+
780
+ FileUtils.mkdir_p class_path(full_name) unless @dry_run
781
+
782
+ cache = if method.singleton then
783
+ @cache[:class_methods]
784
+ else
785
+ @cache[:instance_methods]
786
+ end
787
+ cache[full_name] ||= []
788
+ cache[full_name] << method.name
789
+
790
+ return if @dry_run
791
+
792
+ marshal = Marshal.dump method
793
+
794
+ open method_file(full_name, method.full_name), 'wb' do |io|
795
+ io.write marshal
796
+ end
797
+ end
798
+
799
+ ##
800
+ # Writes the ri data for +page+
801
+
802
+ def save_page page
803
+ return unless page.text?
804
+
805
+ path = page_file page.full_name
806
+
807
+ FileUtils.mkdir_p File.dirname(path) unless @dry_run
808
+
809
+ cache[:pages] ||= []
810
+ cache[:pages] << page.full_name
811
+
812
+ return if @dry_run
813
+
814
+ marshal = Marshal.dump page
815
+
816
+ open path, 'wb' do |io|
817
+ io.write marshal
818
+ end
819
+ end
820
+
821
+ ##
822
+ # Source of the contents of this store.
823
+ #
824
+ # For a store from a gem the source is the gem name. For a store from the
825
+ # home directory the source is "home". For system ri store (the standard
826
+ # library documentation) the source is"ruby". For a store from the site
827
+ # ri directory the store is "site". For other stores the source is the
828
+ # #path.
829
+
830
+ def source
831
+ case type
832
+ when :gem then File.basename File.expand_path '..', @path
833
+ when :home then 'home'
834
+ when :site then 'site'
835
+ when :system then 'ruby'
836
+ else @path
837
+ end
838
+ end
839
+
840
+ ##
841
+ # Gets the title for this RDoc store. This is used as the title in each
842
+ # page on the RDoc server
843
+
844
+ def title
845
+ @cache[:title]
846
+ end
847
+
848
+ ##
849
+ # Sets the title page for this RDoc store.
850
+
851
+ def title= title
852
+ @cache[:title] = title
853
+ end
854
+
855
+ ##
856
+ # Returns the unique classes discovered by RDoc.
857
+ #
858
+ # ::complete must have been called prior to using this method.
859
+
860
+ def unique_classes
861
+ @unique_classes
862
+ end
863
+
864
+ ##
865
+ # Returns the unique classes and modules discovered by RDoc.
866
+ # ::complete must have been called prior to using this method.
867
+
868
+ def unique_classes_and_modules
869
+ @unique_classes + @unique_modules
870
+ end
871
+
872
+ ##
873
+ # Returns the unique modules discovered by RDoc.
874
+ # ::complete must have been called prior to using this method.
875
+
876
+ def unique_modules
877
+ @unique_modules
878
+ end
879
+
880
+ end
881
+