mega-max-hub 0.0.1

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