gitlab-rdoc 6.3.2

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 (196) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING.rdoc +220 -0
  3. data/CVE-2013-0256.rdoc +49 -0
  4. data/ExampleMarkdown.md +37 -0
  5. data/ExampleRDoc.rdoc +208 -0
  6. data/Gemfile +12 -0
  7. data/History.rdoc +1666 -0
  8. data/LEGAL.rdoc +50 -0
  9. data/LICENSE.rdoc +57 -0
  10. data/README.rdoc +133 -0
  11. data/RI.rdoc +57 -0
  12. data/Rakefile +101 -0
  13. data/TODO.rdoc +59 -0
  14. data/bin/console +7 -0
  15. data/bin/setup +6 -0
  16. data/exe/rdoc +44 -0
  17. data/exe/ri +12 -0
  18. data/lib/rdoc/alias.rb +112 -0
  19. data/lib/rdoc/anon_class.rb +11 -0
  20. data/lib/rdoc/any_method.rb +361 -0
  21. data/lib/rdoc/attr.rb +176 -0
  22. data/lib/rdoc/class_module.rb +802 -0
  23. data/lib/rdoc/code_object.rb +421 -0
  24. data/lib/rdoc/code_objects.rb +6 -0
  25. data/lib/rdoc/comment.rb +250 -0
  26. data/lib/rdoc/constant.rb +187 -0
  27. data/lib/rdoc/context/section.rb +232 -0
  28. data/lib/rdoc/context.rb +1266 -0
  29. data/lib/rdoc/cross_reference.rb +202 -0
  30. data/lib/rdoc/encoding.rb +136 -0
  31. data/lib/rdoc/erb_partial.rb +19 -0
  32. data/lib/rdoc/erbio.rb +42 -0
  33. data/lib/rdoc/extend.rb +10 -0
  34. data/lib/rdoc/generator/darkfish.rb +790 -0
  35. data/lib/rdoc/generator/json_index.rb +300 -0
  36. data/lib/rdoc/generator/markup.rb +160 -0
  37. data/lib/rdoc/generator/pot/message_extractor.rb +68 -0
  38. data/lib/rdoc/generator/pot/po.rb +84 -0
  39. data/lib/rdoc/generator/pot/po_entry.rb +141 -0
  40. data/lib/rdoc/generator/pot.rb +98 -0
  41. data/lib/rdoc/generator/ri.rb +31 -0
  42. data/lib/rdoc/generator/template/darkfish/.document +0 -0
  43. data/lib/rdoc/generator/template/darkfish/_footer.rhtml +5 -0
  44. data/lib/rdoc/generator/template/darkfish/_head.rhtml +22 -0
  45. data/lib/rdoc/generator/template/darkfish/_sidebar_VCS_info.rhtml +19 -0
  46. data/lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml +9 -0
  47. data/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml +15 -0
  48. data/lib/rdoc/generator/template/darkfish/_sidebar_in_files.rhtml +9 -0
  49. data/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml +15 -0
  50. data/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml +15 -0
  51. data/lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml +12 -0
  52. data/lib/rdoc/generator/template/darkfish/_sidebar_navigation.rhtml +11 -0
  53. data/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml +12 -0
  54. data/lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml +11 -0
  55. data/lib/rdoc/generator/template/darkfish/_sidebar_search.rhtml +14 -0
  56. data/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml +11 -0
  57. data/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml +18 -0
  58. data/lib/rdoc/generator/template/darkfish/class.rhtml +172 -0
  59. data/lib/rdoc/generator/template/darkfish/css/fonts.css +167 -0
  60. data/lib/rdoc/generator/template/darkfish/css/rdoc.css +639 -0
  61. data/lib/rdoc/generator/template/darkfish/fonts/Lato-Light.ttf +0 -0
  62. data/lib/rdoc/generator/template/darkfish/fonts/Lato-LightItalic.ttf +0 -0
  63. data/lib/rdoc/generator/template/darkfish/fonts/Lato-Regular.ttf +0 -0
  64. data/lib/rdoc/generator/template/darkfish/fonts/Lato-RegularItalic.ttf +0 -0
  65. data/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttf +0 -0
  66. data/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttf +0 -0
  67. data/lib/rdoc/generator/template/darkfish/images/add.png +0 -0
  68. data/lib/rdoc/generator/template/darkfish/images/arrow_up.png +0 -0
  69. data/lib/rdoc/generator/template/darkfish/images/brick.png +0 -0
  70. data/lib/rdoc/generator/template/darkfish/images/brick_link.png +0 -0
  71. data/lib/rdoc/generator/template/darkfish/images/bug.png +0 -0
  72. data/lib/rdoc/generator/template/darkfish/images/bullet_black.png +0 -0
  73. data/lib/rdoc/generator/template/darkfish/images/bullet_toggle_minus.png +0 -0
  74. data/lib/rdoc/generator/template/darkfish/images/bullet_toggle_plus.png +0 -0
  75. data/lib/rdoc/generator/template/darkfish/images/date.png +0 -0
  76. data/lib/rdoc/generator/template/darkfish/images/delete.png +0 -0
  77. data/lib/rdoc/generator/template/darkfish/images/find.png +0 -0
  78. data/lib/rdoc/generator/template/darkfish/images/loadingAnimation.gif +0 -0
  79. data/lib/rdoc/generator/template/darkfish/images/macFFBgHack.png +0 -0
  80. data/lib/rdoc/generator/template/darkfish/images/package.png +0 -0
  81. data/lib/rdoc/generator/template/darkfish/images/page_green.png +0 -0
  82. data/lib/rdoc/generator/template/darkfish/images/page_white_text.png +0 -0
  83. data/lib/rdoc/generator/template/darkfish/images/page_white_width.png +0 -0
  84. data/lib/rdoc/generator/template/darkfish/images/plugin.png +0 -0
  85. data/lib/rdoc/generator/template/darkfish/images/ruby.png +0 -0
  86. data/lib/rdoc/generator/template/darkfish/images/tag_blue.png +0 -0
  87. data/lib/rdoc/generator/template/darkfish/images/tag_green.png +0 -0
  88. data/lib/rdoc/generator/template/darkfish/images/transparent.png +0 -0
  89. data/lib/rdoc/generator/template/darkfish/images/wrench.png +0 -0
  90. data/lib/rdoc/generator/template/darkfish/images/wrench_orange.png +0 -0
  91. data/lib/rdoc/generator/template/darkfish/images/zoom.png +0 -0
  92. data/lib/rdoc/generator/template/darkfish/index.rhtml +22 -0
  93. data/lib/rdoc/generator/template/darkfish/js/darkfish.js +84 -0
  94. data/lib/rdoc/generator/template/darkfish/js/search.js +110 -0
  95. data/lib/rdoc/generator/template/darkfish/page.rhtml +18 -0
  96. data/lib/rdoc/generator/template/darkfish/servlet_not_found.rhtml +18 -0
  97. data/lib/rdoc/generator/template/darkfish/servlet_root.rhtml +62 -0
  98. data/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml +58 -0
  99. data/lib/rdoc/generator/template/json_index/.document +1 -0
  100. data/lib/rdoc/generator/template/json_index/js/navigation.js +105 -0
  101. data/lib/rdoc/generator/template/json_index/js/searcher.js +229 -0
  102. data/lib/rdoc/generator.rb +51 -0
  103. data/lib/rdoc/ghost_method.rb +7 -0
  104. data/lib/rdoc/i18n/locale.rb +102 -0
  105. data/lib/rdoc/i18n/text.rb +126 -0
  106. data/lib/rdoc/i18n.rb +10 -0
  107. data/lib/rdoc/include.rb +10 -0
  108. data/lib/rdoc/known_classes.rb +73 -0
  109. data/lib/rdoc/markdown/entities.rb +2132 -0
  110. data/lib/rdoc/markdown/literals.kpeg +23 -0
  111. data/lib/rdoc/markdown/literals.rb +417 -0
  112. data/lib/rdoc/markdown.kpeg +1237 -0
  113. data/lib/rdoc/markdown.rb +16685 -0
  114. data/lib/rdoc/markup/attr_changer.rb +23 -0
  115. data/lib/rdoc/markup/attr_span.rb +36 -0
  116. data/lib/rdoc/markup/attribute_manager.rb +409 -0
  117. data/lib/rdoc/markup/attributes.rb +71 -0
  118. data/lib/rdoc/markup/blank_line.rb +28 -0
  119. data/lib/rdoc/markup/block_quote.rb +15 -0
  120. data/lib/rdoc/markup/document.rb +165 -0
  121. data/lib/rdoc/markup/formatter.rb +266 -0
  122. data/lib/rdoc/markup/hard_break.rb +32 -0
  123. data/lib/rdoc/markup/heading.rb +79 -0
  124. data/lib/rdoc/markup/include.rb +43 -0
  125. data/lib/rdoc/markup/indented_paragraph.rb +48 -0
  126. data/lib/rdoc/markup/list.rb +102 -0
  127. data/lib/rdoc/markup/list_item.rb +100 -0
  128. data/lib/rdoc/markup/paragraph.rb +29 -0
  129. data/lib/rdoc/markup/parser.rb +575 -0
  130. data/lib/rdoc/markup/pre_process.rb +296 -0
  131. data/lib/rdoc/markup/raw.rb +70 -0
  132. data/lib/rdoc/markup/regexp_handling.rb +41 -0
  133. data/lib/rdoc/markup/rule.rb +21 -0
  134. data/lib/rdoc/markup/table.rb +47 -0
  135. data/lib/rdoc/markup/to_ansi.rb +94 -0
  136. data/lib/rdoc/markup/to_bs.rb +77 -0
  137. data/lib/rdoc/markup/to_html.rb +444 -0
  138. data/lib/rdoc/markup/to_html_crossref.rb +176 -0
  139. data/lib/rdoc/markup/to_html_snippet.rb +285 -0
  140. data/lib/rdoc/markup/to_joined_paragraph.rb +47 -0
  141. data/lib/rdoc/markup/to_label.rb +75 -0
  142. data/lib/rdoc/markup/to_markdown.rb +192 -0
  143. data/lib/rdoc/markup/to_rdoc.rb +362 -0
  144. data/lib/rdoc/markup/to_table_of_contents.rb +89 -0
  145. data/lib/rdoc/markup/to_test.rb +70 -0
  146. data/lib/rdoc/markup/to_tt_only.rb +121 -0
  147. data/lib/rdoc/markup/verbatim.rb +84 -0
  148. data/lib/rdoc/markup.rb +867 -0
  149. data/lib/rdoc/meta_method.rb +7 -0
  150. data/lib/rdoc/method_attr.rb +419 -0
  151. data/lib/rdoc/mixin.rb +121 -0
  152. data/lib/rdoc/normal_class.rb +93 -0
  153. data/lib/rdoc/normal_module.rb +74 -0
  154. data/lib/rdoc/options.rb +1285 -0
  155. data/lib/rdoc/parser/c.rb +1225 -0
  156. data/lib/rdoc/parser/changelog.rb +335 -0
  157. data/lib/rdoc/parser/markdown.rb +24 -0
  158. data/lib/rdoc/parser/rd.rb +23 -0
  159. data/lib/rdoc/parser/ripper_state_lex.rb +590 -0
  160. data/lib/rdoc/parser/ruby.rb +2327 -0
  161. data/lib/rdoc/parser/ruby_tools.rb +167 -0
  162. data/lib/rdoc/parser/simple.rb +61 -0
  163. data/lib/rdoc/parser/text.rb +12 -0
  164. data/lib/rdoc/parser.rb +277 -0
  165. data/lib/rdoc/rd/block_parser.rb +1056 -0
  166. data/lib/rdoc/rd/block_parser.ry +639 -0
  167. data/lib/rdoc/rd/inline.rb +72 -0
  168. data/lib/rdoc/rd/inline_parser.rb +1208 -0
  169. data/lib/rdoc/rd/inline_parser.ry +593 -0
  170. data/lib/rdoc/rd.rb +100 -0
  171. data/lib/rdoc/rdoc.rb +579 -0
  172. data/lib/rdoc/require.rb +52 -0
  173. data/lib/rdoc/ri/driver.rb +1572 -0
  174. data/lib/rdoc/ri/formatter.rb +6 -0
  175. data/lib/rdoc/ri/paths.rb +171 -0
  176. data/lib/rdoc/ri/store.rb +7 -0
  177. data/lib/rdoc/ri/task.rb +71 -0
  178. data/lib/rdoc/ri.rb +21 -0
  179. data/lib/rdoc/rubygems_hook.rb +246 -0
  180. data/lib/rdoc/servlet.rb +451 -0
  181. data/lib/rdoc/single_class.rb +26 -0
  182. data/lib/rdoc/stats/normal.rb +58 -0
  183. data/lib/rdoc/stats/quiet.rb +60 -0
  184. data/lib/rdoc/stats/verbose.rb +46 -0
  185. data/lib/rdoc/stats.rb +462 -0
  186. data/lib/rdoc/store.rb +979 -0
  187. data/lib/rdoc/task.rb +329 -0
  188. data/lib/rdoc/text.rb +304 -0
  189. data/lib/rdoc/token_stream.rb +119 -0
  190. data/lib/rdoc/tom_doc.rb +263 -0
  191. data/lib/rdoc/top_level.rb +289 -0
  192. data/lib/rdoc/version.rb +8 -0
  193. data/lib/rdoc.rb +201 -0
  194. data/man/ri.1 +247 -0
  195. data/rdoc.gemspec +249 -0
  196. metadata +279 -0
@@ -0,0 +1,187 @@
1
+ # frozen_string_literal: true
2
+ ##
3
+ # A constant
4
+
5
+ class RDoc::Constant < RDoc::CodeObject
6
+
7
+ MARSHAL_VERSION = 0 # :nodoc:
8
+
9
+ ##
10
+ # Sets the module or class this is constant is an alias for.
11
+
12
+ attr_writer :is_alias_for
13
+
14
+ ##
15
+ # The constant's name
16
+
17
+ attr_accessor :name
18
+
19
+ ##
20
+ # The constant's value
21
+
22
+ attr_accessor :value
23
+
24
+ ##
25
+ # The constant's visibility
26
+
27
+ attr_accessor :visibility
28
+
29
+ ##
30
+ # Creates a new constant with +name+, +value+ and +comment+
31
+
32
+ def initialize(name, value, comment)
33
+ super()
34
+
35
+ @name = name
36
+ @value = value
37
+
38
+ @is_alias_for = nil
39
+ @visibility = :public
40
+
41
+ self.comment = comment
42
+ end
43
+
44
+ ##
45
+ # Constants are ordered by name
46
+
47
+ def <=> other
48
+ return unless self.class === other
49
+
50
+ [parent_name, name] <=> [other.parent_name, other.name]
51
+ end
52
+
53
+ ##
54
+ # Constants are equal when their #parent and #name is the same
55
+
56
+ def == other
57
+ self.class == other.class and
58
+ @parent == other.parent and
59
+ @name == other.name
60
+ end
61
+
62
+ ##
63
+ # A constant is documented if it has a comment, or is an alias
64
+ # for a documented class or module.
65
+
66
+ def documented?
67
+ return true if super
68
+ return false unless @is_alias_for
69
+ case @is_alias_for
70
+ when String then
71
+ found = @store.find_class_or_module @is_alias_for
72
+ return false unless found
73
+ @is_alias_for = found
74
+ end
75
+ @is_alias_for.documented?
76
+ end
77
+
78
+ ##
79
+ # Full constant name including namespace
80
+
81
+ def full_name
82
+ @full_name ||= "#{parent_name}::#{@name}"
83
+ end
84
+
85
+ ##
86
+ # The module or class this constant is an alias for
87
+
88
+ def is_alias_for
89
+ case @is_alias_for
90
+ when String then
91
+ found = @store.find_class_or_module @is_alias_for
92
+ @is_alias_for = found if found
93
+ @is_alias_for
94
+ else
95
+ @is_alias_for
96
+ end
97
+ end
98
+
99
+ def inspect # :nodoc:
100
+ "#<%s:0x%x %s::%s>" % [
101
+ self.class, object_id,
102
+ parent_name, @name,
103
+ ]
104
+ end
105
+
106
+ ##
107
+ # Dumps this Constant for use by ri. See also #marshal_load
108
+
109
+ def marshal_dump
110
+ alias_name = case found = is_alias_for
111
+ when RDoc::CodeObject then found.full_name
112
+ else found
113
+ end
114
+
115
+ [ MARSHAL_VERSION,
116
+ @name,
117
+ full_name,
118
+ @visibility,
119
+ alias_name,
120
+ parse(@comment),
121
+ @file.relative_name,
122
+ parent.name,
123
+ parent.class,
124
+ section.title,
125
+ ]
126
+ end
127
+
128
+ ##
129
+ # Loads this Constant from +array+. For a loaded Constant the following
130
+ # methods will return cached values:
131
+ #
132
+ # * #full_name
133
+ # * #parent_name
134
+
135
+ def marshal_load array
136
+ initialize array[1], nil, array[5]
137
+
138
+ @full_name = array[2]
139
+ @visibility = array[3] || :public
140
+ @is_alias_for = array[4]
141
+ # 5 handled above
142
+ # 6 handled below
143
+ @parent_name = array[7]
144
+ @parent_class = array[8]
145
+ @section_title = array[9]
146
+
147
+ @file = RDoc::TopLevel.new array[6]
148
+ end
149
+
150
+ ##
151
+ # Path to this constant for use with HTML generator output.
152
+
153
+ def path
154
+ "#{@parent.path}##{@name}"
155
+ end
156
+
157
+ def pretty_print q # :nodoc:
158
+ q.group 2, "[#{self.class.name} #{full_name}", "]" do
159
+ unless comment.empty? then
160
+ q.breakable
161
+ q.text "comment:"
162
+ q.breakable
163
+ q.pp @comment
164
+ end
165
+ end
166
+ end
167
+
168
+ ##
169
+ # Sets the store for this class or module and its contained code objects.
170
+
171
+ def store= store
172
+ super
173
+
174
+ @file = @store.add_file @file.full_name if @file
175
+ end
176
+
177
+ def to_s # :nodoc:
178
+ parent_name = parent ? parent.full_name : '(unknown)'
179
+ if is_alias_for
180
+ "constant #{parent_name}::#@name -> #{is_alias_for}"
181
+ else
182
+ "constant #{parent_name}::#@name"
183
+ end
184
+ end
185
+
186
+ end
187
+
@@ -0,0 +1,232 @@
1
+ # frozen_string_literal: true
2
+ ##
3
+ # A section of documentation like:
4
+ #
5
+ # # :section: The title
6
+ # # The body
7
+ #
8
+ # Sections can be referenced multiple times and will be collapsed into a
9
+ # single section.
10
+
11
+ class RDoc::Context::Section
12
+
13
+ include RDoc::Text
14
+
15
+ MARSHAL_VERSION = 0 # :nodoc:
16
+
17
+ ##
18
+ # Section comment
19
+
20
+ attr_reader :comment
21
+
22
+ ##
23
+ # Section comments
24
+
25
+ attr_reader :comments
26
+
27
+ ##
28
+ # Context this Section lives in
29
+
30
+ attr_reader :parent
31
+
32
+ ##
33
+ # Section title
34
+
35
+ attr_reader :title
36
+
37
+ ##
38
+ # Creates a new section with +title+ and +comment+
39
+
40
+ def initialize parent, title, comment
41
+ @parent = parent
42
+ @title = title ? title.strip : title
43
+
44
+ @comments = []
45
+
46
+ add_comment comment
47
+ end
48
+
49
+ ##
50
+ # Sections are equal when they have the same #title
51
+
52
+ def == other
53
+ self.class === other and @title == other.title
54
+ end
55
+
56
+ alias eql? ==
57
+
58
+ ##
59
+ # Adds +comment+ to this section
60
+
61
+ def add_comment comment
62
+ comment = extract_comment comment
63
+
64
+ return if comment.empty?
65
+
66
+ case comment
67
+ when RDoc::Comment then
68
+ @comments << comment
69
+ when RDoc::Markup::Document then
70
+ @comments.concat comment.parts
71
+ when Array then
72
+ @comments.concat comment
73
+ else
74
+ raise TypeError, "unknown comment type: #{comment.inspect}"
75
+ end
76
+ end
77
+
78
+ ##
79
+ # Anchor reference for linking to this section
80
+
81
+ def aref
82
+ title = @title || '[untitled]'
83
+
84
+ CGI.escape(title).gsub('%', '-').sub(/^-/, '')
85
+ end
86
+
87
+ ##
88
+ # Extracts the comment for this section from the original comment block.
89
+ # If the first line contains :section:, strip it and use the rest.
90
+ # Otherwise remove lines up to the line containing :section:, and look
91
+ # for those lines again at the end and remove them. This lets us write
92
+ #
93
+ # # :section: The title
94
+ # # The body
95
+
96
+ def extract_comment comment
97
+ case comment
98
+ when Array then
99
+ comment.map do |c|
100
+ extract_comment c
101
+ end
102
+ when nil
103
+ RDoc::Comment.new ''
104
+ when RDoc::Comment then
105
+ if comment.text =~ /^#[ \t]*:section:.*\n/ then
106
+ start = $`
107
+ rest = $'
108
+
109
+ comment.text = if start.empty? then
110
+ rest
111
+ else
112
+ rest.sub(/#{start.chomp}\Z/, '')
113
+ end
114
+ end
115
+
116
+ comment
117
+ when RDoc::Markup::Document then
118
+ comment
119
+ else
120
+ raise TypeError, "unknown comment #{comment.inspect}"
121
+ end
122
+ end
123
+
124
+ def inspect # :nodoc:
125
+ "#<%s:0x%x %p>" % [self.class, object_id, title]
126
+ end
127
+
128
+ def hash # :nodoc:
129
+ @title.hash
130
+ end
131
+
132
+ ##
133
+ # The files comments in this section come from
134
+
135
+ def in_files
136
+ return [] if @comments.empty?
137
+
138
+ case @comments
139
+ when Array then
140
+ @comments.map do |comment|
141
+ comment.file
142
+ end
143
+ when RDoc::Markup::Document then
144
+ @comment.parts.map do |document|
145
+ document.file
146
+ end
147
+ else
148
+ raise RDoc::Error, "BUG: unknown comment class #{@comments.class}"
149
+ end
150
+ end
151
+
152
+ ##
153
+ # Serializes this Section. The title and parsed comment are saved, but not
154
+ # the section parent which must be restored manually.
155
+
156
+ def marshal_dump
157
+ [
158
+ MARSHAL_VERSION,
159
+ @title,
160
+ parse,
161
+ ]
162
+ end
163
+
164
+ ##
165
+ # De-serializes this Section. The section parent must be restored manually.
166
+
167
+ def marshal_load array
168
+ @parent = nil
169
+
170
+ @title = array[1]
171
+ @comments = array[2]
172
+ end
173
+
174
+ ##
175
+ # Parses +comment_location+ into an RDoc::Markup::Document composed of
176
+ # multiple RDoc::Markup::Documents with their file set.
177
+
178
+ def parse
179
+ case @comments
180
+ when String then
181
+ super
182
+ when Array then
183
+ docs = @comments.map do |comment, location|
184
+ doc = super comment
185
+ doc.file = location if location
186
+ doc
187
+ end
188
+
189
+ RDoc::Markup::Document.new(*docs)
190
+ when RDoc::Comment then
191
+ doc = super @comments.text, comments.format
192
+ doc.file = @comments.location
193
+ doc
194
+ when RDoc::Markup::Document then
195
+ return @comments
196
+ else
197
+ raise ArgumentError, "unknown comment class #{comments.class}"
198
+ end
199
+ end
200
+
201
+ ##
202
+ # The section's title, or 'Top Section' if the title is nil.
203
+ #
204
+ # This is used by the table of contents template so the name is silly.
205
+
206
+ def plain_html
207
+ @title || 'Top Section'
208
+ end
209
+
210
+ ##
211
+ # Removes a comment from this section if it is from the same file as
212
+ # +comment+
213
+
214
+ def remove_comment comment
215
+ return if @comments.empty?
216
+
217
+ case @comments
218
+ when Array then
219
+ @comments.delete_if do |my_comment|
220
+ my_comment.file == comment.file
221
+ end
222
+ when RDoc::Markup::Document then
223
+ @comments.parts.delete_if do |document|
224
+ document.file == comment.file.name
225
+ end
226
+ else
227
+ raise RDoc::Error, "BUG: unknown comment class #{@comments.class}"
228
+ end
229
+ end
230
+
231
+ end
232
+
@@ -0,0 +1,1266 @@
1
+ # frozen_string_literal: true
2
+ require 'cgi'
3
+
4
+ ##
5
+ # A Context is something that can hold modules, classes, methods, attributes,
6
+ # aliases, requires, and includes. Classes, modules, and files are all
7
+ # Contexts.
8
+
9
+ class RDoc::Context < RDoc::CodeObject
10
+
11
+ include Comparable
12
+
13
+ ##
14
+ # Types of methods
15
+
16
+ TYPES = %w[class instance]
17
+
18
+ ##
19
+ # If a context has these titles it will be sorted in this order.
20
+
21
+ TOMDOC_TITLES = [nil, 'Public', 'Internal', 'Deprecated'] # :nodoc:
22
+ TOMDOC_TITLES_SORT = TOMDOC_TITLES.sort_by { |title| title.to_s } # :nodoc:
23
+
24
+ ##
25
+ # Class/module aliases
26
+
27
+ attr_reader :aliases
28
+
29
+ ##
30
+ # All attr* methods
31
+
32
+ attr_reader :attributes
33
+
34
+ ##
35
+ # Block params to be used in the next MethodAttr parsed under this context
36
+
37
+ attr_accessor :block_params
38
+
39
+ ##
40
+ # Constants defined
41
+
42
+ attr_reader :constants
43
+
44
+ ##
45
+ # Sets the current documentation section of documentation
46
+
47
+ attr_writer :current_section
48
+
49
+ ##
50
+ # Files this context is found in
51
+
52
+ attr_reader :in_files
53
+
54
+ ##
55
+ # Modules this context includes
56
+
57
+ attr_reader :includes
58
+
59
+ ##
60
+ # Modules this context is extended with
61
+
62
+ attr_reader :extends
63
+
64
+ ##
65
+ # Methods defined in this context
66
+
67
+ attr_reader :method_list
68
+
69
+ ##
70
+ # Name of this class excluding namespace. See also full_name
71
+
72
+ attr_reader :name
73
+
74
+ ##
75
+ # Files this context requires
76
+
77
+ attr_reader :requires
78
+
79
+ ##
80
+ # Use this section for the next method, attribute or constant added.
81
+
82
+ attr_accessor :temporary_section
83
+
84
+ ##
85
+ # Hash <tt>old_name => [aliases]</tt>, for aliases
86
+ # that haven't (yet) been resolved to a method/attribute.
87
+ # (Not to be confused with the aliases of the context.)
88
+
89
+ attr_accessor :unmatched_alias_lists
90
+
91
+ ##
92
+ # Aliases that could not be resolved.
93
+
94
+ attr_reader :external_aliases
95
+
96
+ ##
97
+ # Current visibility of this context
98
+
99
+ attr_accessor :visibility
100
+
101
+ ##
102
+ # Current visibility of this line
103
+
104
+ attr_writer :current_line_visibility
105
+
106
+ ##
107
+ # Hash of registered methods. Attributes are also registered here,
108
+ # twice if they are RW.
109
+
110
+ attr_reader :methods_hash
111
+
112
+ ##
113
+ # Params to be used in the next MethodAttr parsed under this context
114
+
115
+ attr_accessor :params
116
+
117
+ ##
118
+ # Hash of registered constants.
119
+
120
+ attr_reader :constants_hash
121
+
122
+ ##
123
+ # Creates an unnamed empty context with public current visibility
124
+
125
+ def initialize
126
+ super
127
+
128
+ @in_files = []
129
+
130
+ @name ||= "unknown"
131
+ @parent = nil
132
+ @visibility = :public
133
+
134
+ @current_section = Section.new self, nil, nil
135
+ @sections = { nil => @current_section }
136
+ @temporary_section = nil
137
+
138
+ @classes = {}
139
+ @modules = {}
140
+
141
+ initialize_methods_etc
142
+ end
143
+
144
+ ##
145
+ # Sets the defaults for methods and so-forth
146
+
147
+ def initialize_methods_etc
148
+ @method_list = []
149
+ @attributes = []
150
+ @aliases = []
151
+ @requires = []
152
+ @includes = []
153
+ @extends = []
154
+ @constants = []
155
+ @external_aliases = []
156
+ @current_line_visibility = nil
157
+
158
+ # This Hash maps a method name to a list of unmatched aliases (aliases of
159
+ # a method not yet encountered).
160
+ @unmatched_alias_lists = {}
161
+
162
+ @methods_hash = {}
163
+ @constants_hash = {}
164
+
165
+ @params = nil
166
+
167
+ @store ||= nil
168
+ end
169
+
170
+ ##
171
+ # Contexts are sorted by full_name
172
+
173
+ def <=>(other)
174
+ return nil unless RDoc::CodeObject === other
175
+
176
+ full_name <=> other.full_name
177
+ end
178
+
179
+ ##
180
+ # Adds an item of type +klass+ with the given +name+ and +comment+ to the
181
+ # context.
182
+ #
183
+ # Currently only RDoc::Extend and RDoc::Include are supported.
184
+
185
+ def add klass, name, comment
186
+ if RDoc::Extend == klass then
187
+ ext = RDoc::Extend.new name, comment
188
+ add_extend ext
189
+ elsif RDoc::Include == klass then
190
+ incl = RDoc::Include.new name, comment
191
+ add_include incl
192
+ else
193
+ raise NotImplementedError, "adding a #{klass} is not implemented"
194
+ end
195
+ end
196
+
197
+ ##
198
+ # Adds +an_alias+ that is automatically resolved
199
+
200
+ def add_alias an_alias
201
+ return an_alias unless @document_self
202
+
203
+ method_attr = find_method(an_alias.old_name, an_alias.singleton) ||
204
+ find_attribute(an_alias.old_name, an_alias.singleton)
205
+
206
+ if method_attr then
207
+ method_attr.add_alias an_alias, self
208
+ else
209
+ add_to @external_aliases, an_alias
210
+ unmatched_alias_list =
211
+ @unmatched_alias_lists[an_alias.pretty_old_name] ||= []
212
+ unmatched_alias_list.push an_alias
213
+ end
214
+
215
+ an_alias
216
+ end
217
+
218
+ ##
219
+ # Adds +attribute+ if not already there. If it is (as method(s) or attribute),
220
+ # updates the comment if it was empty.
221
+ #
222
+ # The attribute is registered only if it defines a new method.
223
+ # For instance, <tt>attr_reader :foo</tt> will not be registered
224
+ # if method +foo+ exists, but <tt>attr_accessor :foo</tt> will be registered
225
+ # if method +foo+ exists, but <tt>foo=</tt> does not.
226
+
227
+ def add_attribute attribute
228
+ return attribute unless @document_self
229
+
230
+ # mainly to check for redefinition of an attribute as a method
231
+ # TODO find a policy for 'attr_reader :foo' + 'def foo=()'
232
+ register = false
233
+
234
+ key = nil
235
+
236
+ if attribute.rw.index 'R' then
237
+ key = attribute.pretty_name
238
+ known = @methods_hash[key]
239
+
240
+ if known then
241
+ known.comment = attribute.comment if known.comment.empty?
242
+ elsif registered = @methods_hash[attribute.pretty_name + '='] and
243
+ RDoc::Attr === registered then
244
+ registered.rw = 'RW'
245
+ else
246
+ @methods_hash[key] = attribute
247
+ register = true
248
+ end
249
+ end
250
+
251
+ if attribute.rw.index 'W' then
252
+ key = attribute.pretty_name + '='
253
+ known = @methods_hash[key]
254
+
255
+ if known then
256
+ known.comment = attribute.comment if known.comment.empty?
257
+ elsif registered = @methods_hash[attribute.pretty_name] and
258
+ RDoc::Attr === registered then
259
+ registered.rw = 'RW'
260
+ else
261
+ @methods_hash[key] = attribute
262
+ register = true
263
+ end
264
+ end
265
+
266
+ if register then
267
+ attribute.visibility = @visibility
268
+ add_to @attributes, attribute
269
+ resolve_aliases attribute
270
+ end
271
+
272
+ attribute
273
+ end
274
+
275
+ ##
276
+ # Adds a class named +given_name+ with +superclass+.
277
+ #
278
+ # Both +given_name+ and +superclass+ may contain '::', and are
279
+ # interpreted relative to the +self+ context. This allows handling correctly
280
+ # examples like these:
281
+ # class RDoc::Gauntlet < Gauntlet
282
+ # module Mod
283
+ # class Object # implies < ::Object
284
+ # class SubObject < Object # this is _not_ ::Object
285
+ #
286
+ # Given <tt>class Container::Item</tt> RDoc assumes +Container+ is a module
287
+ # unless it later sees <tt>class Container</tt>. +add_class+ automatically
288
+ # upgrades +given_name+ to a class in this case.
289
+
290
+ def add_class class_type, given_name, superclass = '::Object'
291
+ # superclass +nil+ is passed by the C parser in the following cases:
292
+ # - registering Object in 1.8 (correct)
293
+ # - registering BasicObject in 1.9 (correct)
294
+ # - registering RubyVM in 1.9 in iseq.c (incorrect: < Object in vm.c)
295
+ #
296
+ # If we later find a superclass for a registered class with a nil
297
+ # superclass, we must honor it.
298
+
299
+ # find the name & enclosing context
300
+ if given_name =~ /^:+(\w+)$/ then
301
+ full_name = $1
302
+ enclosing = top_level
303
+ name = full_name.split(/:+/).last
304
+ else
305
+ full_name = child_name given_name
306
+
307
+ if full_name =~ /^(.+)::(\w+)$/ then
308
+ name = $2
309
+ ename = $1
310
+ enclosing = @store.classes_hash[ename] || @store.modules_hash[ename]
311
+ # HACK: crashes in actionpack/lib/action_view/helpers/form_helper.rb (metaprogramming)
312
+ unless enclosing then
313
+ # try the given name at top level (will work for the above example)
314
+ enclosing = @store.classes_hash[given_name] ||
315
+ @store.modules_hash[given_name]
316
+ return enclosing if enclosing
317
+ # not found: create the parent(s)
318
+ names = ename.split('::')
319
+ enclosing = self
320
+ names.each do |n|
321
+ enclosing = enclosing.classes_hash[n] ||
322
+ enclosing.modules_hash[n] ||
323
+ enclosing.add_module(RDoc::NormalModule, n)
324
+ end
325
+ end
326
+ else
327
+ name = full_name
328
+ enclosing = self
329
+ end
330
+ end
331
+
332
+ # fix up superclass
333
+ if full_name == 'BasicObject' then
334
+ superclass = nil
335
+ elsif full_name == 'Object' then
336
+ superclass = '::BasicObject'
337
+ end
338
+
339
+ # find the superclass full name
340
+ if superclass then
341
+ if superclass =~ /^:+/ then
342
+ superclass = $' #'
343
+ else
344
+ if superclass =~ /^(\w+):+(.+)$/ then
345
+ suffix = $2
346
+ mod = find_module_named($1)
347
+ superclass = mod.full_name + '::' + suffix if mod
348
+ else
349
+ mod = find_module_named(superclass)
350
+ superclass = mod.full_name if mod
351
+ end
352
+ end
353
+
354
+ # did we believe it was a module?
355
+ mod = @store.modules_hash.delete superclass
356
+
357
+ upgrade_to_class mod, RDoc::NormalClass, mod.parent if mod
358
+
359
+ # e.g., Object < Object
360
+ superclass = nil if superclass == full_name
361
+ end
362
+
363
+ klass = @store.classes_hash[full_name]
364
+
365
+ if klass then
366
+ # if TopLevel, it may not be registered in the classes:
367
+ enclosing.classes_hash[name] = klass
368
+
369
+ # update the superclass if needed
370
+ if superclass then
371
+ existing = klass.superclass
372
+ existing = existing.full_name unless existing.is_a?(String) if existing
373
+ if existing.nil? ||
374
+ (existing == 'Object' && superclass != 'Object') then
375
+ klass.superclass = superclass
376
+ end
377
+ end
378
+ else
379
+ # this is a new class
380
+ mod = @store.modules_hash.delete full_name
381
+
382
+ if mod then
383
+ klass = upgrade_to_class mod, RDoc::NormalClass, enclosing
384
+
385
+ klass.superclass = superclass unless superclass.nil?
386
+ else
387
+ klass = class_type.new name, superclass
388
+
389
+ enclosing.add_class_or_module(klass, enclosing.classes_hash,
390
+ @store.classes_hash)
391
+ end
392
+ end
393
+
394
+ klass.parent = self
395
+
396
+ klass
397
+ end
398
+
399
+ ##
400
+ # Adds the class or module +mod+ to the modules or
401
+ # classes Hash +self_hash+, and to +all_hash+ (either
402
+ # <tt>TopLevel::modules_hash</tt> or <tt>TopLevel::classes_hash</tt>),
403
+ # unless #done_documenting is +true+. Sets the #parent of +mod+
404
+ # to +self+, and its #section to #current_section. Returns +mod+.
405
+
406
+ def add_class_or_module mod, self_hash, all_hash
407
+ mod.section = current_section # TODO declaring context? something is
408
+ # wrong here...
409
+ mod.parent = self
410
+ mod.full_name = nil
411
+ mod.store = @store
412
+
413
+ unless @done_documenting then
414
+ self_hash[mod.name] = mod
415
+ # this must be done AFTER adding mod to its parent, so that the full
416
+ # name is correct:
417
+ all_hash[mod.full_name] = mod
418
+ if @store.unmatched_constant_alias[mod.full_name] then
419
+ to, file = @store.unmatched_constant_alias[mod.full_name]
420
+ add_module_alias mod, mod.name, to, file
421
+ end
422
+ end
423
+
424
+ mod
425
+ end
426
+
427
+ ##
428
+ # Adds +constant+ if not already there. If it is, updates the comment,
429
+ # value and/or is_alias_for of the known constant if they were empty/nil.
430
+
431
+ def add_constant constant
432
+ return constant unless @document_self
433
+
434
+ # HACK: avoid duplicate 'PI' & 'E' in math.c (1.8.7 source code)
435
+ # (this is a #ifdef: should be handled by the C parser)
436
+ known = @constants_hash[constant.name]
437
+
438
+ if known then
439
+ known.comment = constant.comment if known.comment.empty?
440
+
441
+ known.value = constant.value if
442
+ known.value.nil? or known.value.strip.empty?
443
+
444
+ known.is_alias_for ||= constant.is_alias_for
445
+ else
446
+ @constants_hash[constant.name] = constant
447
+ add_to @constants, constant
448
+ end
449
+
450
+ constant
451
+ end
452
+
453
+ ##
454
+ # Adds included module +include+ which should be an RDoc::Include
455
+
456
+ def add_include include
457
+ add_to @includes, include
458
+
459
+ include
460
+ end
461
+
462
+ ##
463
+ # Adds extension module +ext+ which should be an RDoc::Extend
464
+
465
+ def add_extend ext
466
+ add_to @extends, ext
467
+
468
+ ext
469
+ end
470
+
471
+ ##
472
+ # Adds +method+ if not already there. If it is (as method or attribute),
473
+ # updates the comment if it was empty.
474
+
475
+ def add_method method
476
+ return method unless @document_self
477
+
478
+ # HACK: avoid duplicate 'new' in io.c & struct.c (1.8.7 source code)
479
+ key = method.pretty_name
480
+ known = @methods_hash[key]
481
+
482
+ if known then
483
+ if @store then # otherwise we are loading
484
+ known.comment = method.comment if known.comment.empty?
485
+ previously = ", previously in #{known.file}" unless
486
+ method.file == known.file
487
+ @store.rdoc.options.warn \
488
+ "Duplicate method #{known.full_name} in #{method.file}#{previously}"
489
+ end
490
+ else
491
+ @methods_hash[key] = method
492
+ if @current_line_visibility
493
+ method.visibility, @current_line_visibility = @current_line_visibility, nil
494
+ else
495
+ method.visibility = @visibility
496
+ end
497
+ add_to @method_list, method
498
+ resolve_aliases method
499
+ end
500
+
501
+ method
502
+ end
503
+
504
+ ##
505
+ # Adds a module named +name+. If RDoc already knows +name+ is a class then
506
+ # that class is returned instead. See also #add_class.
507
+
508
+ def add_module(class_type, name)
509
+ mod = @classes[name] || @modules[name]
510
+ return mod if mod
511
+
512
+ full_name = child_name name
513
+ mod = @store.modules_hash[full_name] || class_type.new(name)
514
+
515
+ add_class_or_module mod, @modules, @store.modules_hash
516
+ end
517
+
518
+ ##
519
+ # Adds a module by +RDoc::NormalModule+ instance. See also #add_module.
520
+
521
+ def add_module_by_normal_module(mod)
522
+ add_class_or_module mod, @modules, @store.modules_hash
523
+ end
524
+
525
+ ##
526
+ # Adds an alias from +from+ (a class or module) to +name+ which was defined
527
+ # in +file+.
528
+
529
+ def add_module_alias from, from_name, to, file
530
+ return from if @done_documenting
531
+
532
+ to_full_name = child_name to.name
533
+
534
+ # if we already know this name, don't register an alias:
535
+ # see the metaprogramming in lib/active_support/basic_object.rb,
536
+ # where we already know BasicObject is a class when we find
537
+ # BasicObject = BlankSlate
538
+ return from if @store.find_class_or_module to_full_name
539
+
540
+ unless from
541
+ @store.unmatched_constant_alias[child_name(from_name)] = [to, file]
542
+ return to
543
+ end
544
+
545
+ new_to = from.dup
546
+ new_to.name = to.name
547
+ new_to.full_name = nil
548
+
549
+ if new_to.module? then
550
+ @store.modules_hash[to_full_name] = new_to
551
+ @modules[to.name] = new_to
552
+ else
553
+ @store.classes_hash[to_full_name] = new_to
554
+ @classes[to.name] = new_to
555
+ end
556
+
557
+ # Registers a constant for this alias. The constant value and comment
558
+ # will be updated later, when the Ruby parser adds the constant
559
+ const = RDoc::Constant.new to.name, nil, new_to.comment
560
+ const.record_location file
561
+ const.is_alias_for = from
562
+ add_constant const
563
+
564
+ new_to
565
+ end
566
+
567
+ ##
568
+ # Adds +require+ to this context's top level
569
+
570
+ def add_require(require)
571
+ return require unless @document_self
572
+
573
+ if RDoc::TopLevel === self then
574
+ add_to @requires, require
575
+ else
576
+ parent.add_require require
577
+ end
578
+ end
579
+
580
+ ##
581
+ # Returns a section with +title+, creating it if it doesn't already exist.
582
+ # +comment+ will be appended to the section's comment.
583
+ #
584
+ # A section with a +title+ of +nil+ will return the default section.
585
+ #
586
+ # See also RDoc::Context::Section
587
+
588
+ def add_section title, comment = nil
589
+ if section = @sections[title] then
590
+ section.add_comment comment if comment
591
+ else
592
+ section = Section.new self, title, comment
593
+ @sections[title] = section
594
+ end
595
+
596
+ section
597
+ end
598
+
599
+ ##
600
+ # Adds +thing+ to the collection +array+
601
+
602
+ def add_to array, thing
603
+ array << thing if @document_self
604
+
605
+ thing.parent = self
606
+ thing.store = @store if @store
607
+ thing.section = current_section
608
+ end
609
+
610
+ ##
611
+ # Is there any content?
612
+ #
613
+ # This means any of: comment, aliases, methods, attributes, external
614
+ # aliases, require, constant.
615
+ #
616
+ # Includes and extends are also checked unless <tt>includes == false</tt>.
617
+
618
+ def any_content(includes = true)
619
+ @any_content ||= !(
620
+ @comment.empty? &&
621
+ @method_list.empty? &&
622
+ @attributes.empty? &&
623
+ @aliases.empty? &&
624
+ @external_aliases.empty? &&
625
+ @requires.empty? &&
626
+ @constants.empty?
627
+ )
628
+ @any_content || (includes && !(@includes + @extends).empty? )
629
+ end
630
+
631
+ ##
632
+ # Creates the full name for a child with +name+
633
+
634
+ def child_name name
635
+ if name =~ /^:+/
636
+ $' #'
637
+ elsif RDoc::TopLevel === self then
638
+ name
639
+ else
640
+ "#{self.full_name}::#{name}"
641
+ end
642
+ end
643
+
644
+ ##
645
+ # Class attributes
646
+
647
+ def class_attributes
648
+ @class_attributes ||= attributes.select { |a| a.singleton }
649
+ end
650
+
651
+ ##
652
+ # Class methods
653
+
654
+ def class_method_list
655
+ @class_method_list ||= method_list.select { |a| a.singleton }
656
+ end
657
+
658
+ ##
659
+ # Array of classes in this context
660
+
661
+ def classes
662
+ @classes.values
663
+ end
664
+
665
+ ##
666
+ # All classes and modules in this namespace
667
+
668
+ def classes_and_modules
669
+ classes + modules
670
+ end
671
+
672
+ ##
673
+ # Hash of classes keyed by class name
674
+
675
+ def classes_hash
676
+ @classes
677
+ end
678
+
679
+ ##
680
+ # The current documentation section that new items will be added to. If
681
+ # temporary_section is available it will be used.
682
+
683
+ def current_section
684
+ if section = @temporary_section then
685
+ @temporary_section = nil
686
+ else
687
+ section = @current_section
688
+ end
689
+
690
+ section
691
+ end
692
+
693
+ ##
694
+ # Is part of this thing was defined in +file+?
695
+
696
+ def defined_in?(file)
697
+ @in_files.include?(file)
698
+ end
699
+
700
+ def display(method_attr) # :nodoc:
701
+ if method_attr.is_a? RDoc::Attr
702
+ "#{method_attr.definition} #{method_attr.pretty_name}"
703
+ else
704
+ "method #{method_attr.pretty_name}"
705
+ end
706
+ end
707
+
708
+ ##
709
+ # Iterator for ancestors for duck-typing. Does nothing. See
710
+ # RDoc::ClassModule#each_ancestor.
711
+ #
712
+ # This method exists to make it easy to work with Context subclasses that
713
+ # aren't part of RDoc.
714
+
715
+ def each_ancestor # :nodoc:
716
+ end
717
+
718
+ ##
719
+ # Iterator for attributes
720
+
721
+ def each_attribute # :yields: attribute
722
+ @attributes.each { |a| yield a }
723
+ end
724
+
725
+ ##
726
+ # Iterator for classes and modules
727
+
728
+ def each_classmodule(&block) # :yields: module
729
+ classes_and_modules.sort.each(&block)
730
+ end
731
+
732
+ ##
733
+ # Iterator for constants
734
+
735
+ def each_constant # :yields: constant
736
+ @constants.each {|c| yield c}
737
+ end
738
+
739
+ ##
740
+ # Iterator for included modules
741
+
742
+ def each_include # :yields: include
743
+ @includes.each do |i| yield i end
744
+ end
745
+
746
+ ##
747
+ # Iterator for extension modules
748
+
749
+ def each_extend # :yields: extend
750
+ @extends.each do |e| yield e end
751
+ end
752
+
753
+ ##
754
+ # Iterator for methods
755
+
756
+ def each_method # :yields: method
757
+ return enum_for __method__ unless block_given?
758
+
759
+ @method_list.sort.each { |m| yield m }
760
+ end
761
+
762
+ ##
763
+ # Iterator for each section's contents sorted by title. The +section+, the
764
+ # section's +constants+ and the sections +attributes+ are yielded. The
765
+ # +constants+ and +attributes+ collections are sorted.
766
+ #
767
+ # To retrieve methods in a section use #methods_by_type with the optional
768
+ # +section+ parameter.
769
+ #
770
+ # NOTE: Do not edit collections yielded by this method
771
+
772
+ def each_section # :yields: section, constants, attributes
773
+ return enum_for __method__ unless block_given?
774
+
775
+ constants = @constants.group_by do |constant| constant.section end
776
+ attributes = @attributes.group_by do |attribute| attribute.section end
777
+
778
+ constants.default = []
779
+ attributes.default = []
780
+
781
+ sort_sections.each do |section|
782
+ yield section, constants[section].select(&:display?).sort, attributes[section].select(&:display?).sort
783
+ end
784
+ end
785
+
786
+ ##
787
+ # Finds an attribute +name+ with singleton value +singleton+.
788
+
789
+ def find_attribute(name, singleton)
790
+ name = $1 if name =~ /^(.*)=$/
791
+ @attributes.find { |a| a.name == name && a.singleton == singleton }
792
+ end
793
+
794
+ ##
795
+ # Finds an attribute with +name+ in this context
796
+
797
+ def find_attribute_named(name)
798
+ case name
799
+ when /\A#/ then
800
+ find_attribute name[1..-1], false
801
+ when /\A::/ then
802
+ find_attribute name[2..-1], true
803
+ else
804
+ @attributes.find { |a| a.name == name }
805
+ end
806
+ end
807
+
808
+ ##
809
+ # Finds a class method with +name+ in this context
810
+
811
+ def find_class_method_named(name)
812
+ @method_list.find { |meth| meth.singleton && meth.name == name }
813
+ end
814
+
815
+ ##
816
+ # Finds a constant with +name+ in this context
817
+
818
+ def find_constant_named(name)
819
+ @constants.find do |m|
820
+ m.name == name || m.full_name == name
821
+ end
822
+ end
823
+
824
+ ##
825
+ # Find a module at a higher scope
826
+
827
+ def find_enclosing_module_named(name)
828
+ parent && parent.find_module_named(name)
829
+ end
830
+
831
+ ##
832
+ # Finds an external alias +name+ with singleton value +singleton+.
833
+
834
+ def find_external_alias(name, singleton)
835
+ @external_aliases.find { |m| m.name == name && m.singleton == singleton }
836
+ end
837
+
838
+ ##
839
+ # Finds an external alias with +name+ in this context
840
+
841
+ def find_external_alias_named(name)
842
+ case name
843
+ when /\A#/ then
844
+ find_external_alias name[1..-1], false
845
+ when /\A::/ then
846
+ find_external_alias name[2..-1], true
847
+ else
848
+ @external_aliases.find { |a| a.name == name }
849
+ end
850
+ end
851
+
852
+ ##
853
+ # Finds a file with +name+ in this context
854
+
855
+ def find_file_named name
856
+ @store.find_file_named name
857
+ end
858
+
859
+ ##
860
+ # Finds an instance method with +name+ in this context
861
+
862
+ def find_instance_method_named(name)
863
+ @method_list.find { |meth| !meth.singleton && meth.name == name }
864
+ end
865
+
866
+ ##
867
+ # Finds a method, constant, attribute, external alias, module or file
868
+ # named +symbol+ in this context.
869
+
870
+ def find_local_symbol(symbol)
871
+ find_method_named(symbol) or
872
+ find_constant_named(symbol) or
873
+ find_attribute_named(symbol) or
874
+ find_external_alias_named(symbol) or
875
+ find_module_named(symbol) or
876
+ find_file_named(symbol)
877
+ end
878
+
879
+ ##
880
+ # Finds a method named +name+ with singleton value +singleton+.
881
+
882
+ def find_method(name, singleton)
883
+ @method_list.find { |m|
884
+ if m.singleton
885
+ m.name == name && m.singleton == singleton
886
+ else
887
+ m.name == name && !m.singleton && !singleton
888
+ end
889
+ }
890
+ end
891
+
892
+ ##
893
+ # Finds a instance or module method with +name+ in this context
894
+
895
+ def find_method_named(name)
896
+ case name
897
+ when /\A#/ then
898
+ find_method name[1..-1], false
899
+ when /\A::/ then
900
+ find_method name[2..-1], true
901
+ else
902
+ @method_list.find { |meth| meth.name == name }
903
+ end
904
+ end
905
+
906
+ ##
907
+ # Find a module with +name+ using ruby's scoping rules
908
+
909
+ def find_module_named(name)
910
+ res = @modules[name] || @classes[name]
911
+ return res if res
912
+ return self if self.name == name
913
+ find_enclosing_module_named name
914
+ end
915
+
916
+ ##
917
+ # Look up +symbol+, first as a module, then as a local symbol.
918
+
919
+ def find_symbol(symbol)
920
+ find_symbol_module(symbol) || find_local_symbol(symbol)
921
+ end
922
+
923
+ ##
924
+ # Look up a module named +symbol+.
925
+
926
+ def find_symbol_module(symbol)
927
+ result = nil
928
+
929
+ # look for a class or module 'symbol'
930
+ case symbol
931
+ when /^::/ then
932
+ result = @store.find_class_or_module symbol
933
+ when /^(\w+):+(.+)$/
934
+ suffix = $2
935
+ top = $1
936
+ searched = self
937
+ while searched do
938
+ mod = searched.find_module_named(top)
939
+ break unless mod
940
+ result = @store.find_class_or_module "#{mod.full_name}::#{suffix}"
941
+ break if result || searched.is_a?(RDoc::TopLevel)
942
+ searched = searched.parent
943
+ end
944
+ else
945
+ searched = self
946
+ while searched do
947
+ result = searched.find_module_named(symbol)
948
+ break if result || searched.is_a?(RDoc::TopLevel)
949
+ searched = searched.parent
950
+ end
951
+ end
952
+
953
+ result
954
+ end
955
+
956
+ ##
957
+ # The full name for this context. This method is overridden by subclasses.
958
+
959
+ def full_name
960
+ '(unknown)'
961
+ end
962
+
963
+ ##
964
+ # Does this context and its methods and constants all have documentation?
965
+ #
966
+ # (Yes, fully documented doesn't mean everything.)
967
+
968
+ def fully_documented?
969
+ documented? and
970
+ attributes.all? { |a| a.documented? } and
971
+ method_list.all? { |m| m.documented? } and
972
+ constants.all? { |c| c.documented? }
973
+ end
974
+
975
+ ##
976
+ # URL for this with a +prefix+
977
+
978
+ def http_url(prefix)
979
+ path = name_for_path
980
+ path = path.gsub(/<<\s*(\w*)/, 'from-\1') if path =~ /<</
981
+ path = [prefix] + path.split('::')
982
+
983
+ File.join(*path.compact) + '.html'
984
+ end
985
+
986
+ ##
987
+ # Instance attributes
988
+
989
+ def instance_attributes
990
+ @instance_attributes ||= attributes.reject { |a| a.singleton }
991
+ end
992
+
993
+ ##
994
+ # Instance methods
995
+
996
+ def instance_methods
997
+ @instance_methods ||= method_list.reject { |a| a.singleton }
998
+ end
999
+
1000
+ ##
1001
+ # Instance methods
1002
+ #--
1003
+ # TODO remove this later
1004
+
1005
+ def instance_method_list
1006
+ warn '#instance_method_list is obsoleted, please use #instance_methods'
1007
+ @instance_methods ||= method_list.reject { |a| a.singleton }
1008
+ end
1009
+
1010
+ ##
1011
+ # Breaks method_list into a nested hash by type (<tt>'class'</tt> or
1012
+ # <tt>'instance'</tt>) and visibility (+:public+, +:protected+, +:private+).
1013
+ #
1014
+ # If +section+ is provided only methods in that RDoc::Context::Section will
1015
+ # be returned.
1016
+
1017
+ def methods_by_type section = nil
1018
+ methods = {}
1019
+
1020
+ TYPES.each do |type|
1021
+ visibilities = {}
1022
+ RDoc::VISIBILITIES.each do |vis|
1023
+ visibilities[vis] = []
1024
+ end
1025
+
1026
+ methods[type] = visibilities
1027
+ end
1028
+
1029
+ each_method do |method|
1030
+ next if section and not method.section == section
1031
+ methods[method.type][method.visibility] << method
1032
+ end
1033
+
1034
+ methods
1035
+ end
1036
+
1037
+ ##
1038
+ # Yields AnyMethod and Attr entries matching the list of names in +methods+.
1039
+
1040
+ def methods_matching(methods, singleton = false, &block)
1041
+ (@method_list + @attributes).each do |m|
1042
+ yield m if methods.include?(m.name) and m.singleton == singleton
1043
+ end
1044
+
1045
+ each_ancestor do |parent|
1046
+ parent.methods_matching(methods, singleton, &block)
1047
+ end
1048
+ end
1049
+
1050
+ ##
1051
+ # Array of modules in this context
1052
+
1053
+ def modules
1054
+ @modules.values
1055
+ end
1056
+
1057
+ ##
1058
+ # Hash of modules keyed by module name
1059
+
1060
+ def modules_hash
1061
+ @modules
1062
+ end
1063
+
1064
+ ##
1065
+ # Name to use to generate the url.
1066
+ # <tt>#full_name</tt> by default.
1067
+
1068
+ def name_for_path
1069
+ full_name
1070
+ end
1071
+
1072
+ ##
1073
+ # Changes the visibility for new methods to +visibility+
1074
+
1075
+ def ongoing_visibility=(visibility)
1076
+ @visibility = visibility
1077
+ end
1078
+
1079
+ ##
1080
+ # Record +top_level+ as a file +self+ is in.
1081
+
1082
+ def record_location(top_level)
1083
+ @in_files << top_level unless @in_files.include?(top_level)
1084
+ end
1085
+
1086
+ ##
1087
+ # Should we remove this context from the documentation?
1088
+ #
1089
+ # The answer is yes if:
1090
+ # * #received_nodoc is +true+
1091
+ # * #any_content is +false+ (not counting includes)
1092
+ # * All #includes are modules (not a string), and their module has
1093
+ # <tt>#remove_from_documentation? == true</tt>
1094
+ # * All classes and modules have <tt>#remove_from_documentation? == true</tt>
1095
+
1096
+ def remove_from_documentation?
1097
+ @remove_from_documentation ||=
1098
+ @received_nodoc &&
1099
+ !any_content(false) &&
1100
+ @includes.all? { |i| !i.module.is_a?(String) && i.module.remove_from_documentation? } &&
1101
+ classes_and_modules.all? { |cm| cm.remove_from_documentation? }
1102
+ end
1103
+
1104
+ ##
1105
+ # Removes methods and attributes with a visibility less than +min_visibility+.
1106
+ #--
1107
+ # TODO mark the visibility of attributes in the template (if not public?)
1108
+
1109
+ def remove_invisible min_visibility
1110
+ return if [:private, :nodoc].include? min_visibility
1111
+ remove_invisible_in @method_list, min_visibility
1112
+ remove_invisible_in @attributes, min_visibility
1113
+ remove_invisible_in @constants, min_visibility
1114
+ end
1115
+
1116
+ ##
1117
+ # Only called when min_visibility == :public or :private
1118
+
1119
+ def remove_invisible_in array, min_visibility # :nodoc:
1120
+ if min_visibility == :public then
1121
+ array.reject! { |e|
1122
+ e.visibility != :public and not e.force_documentation
1123
+ }
1124
+ else
1125
+ array.reject! { |e|
1126
+ e.visibility == :private and not e.force_documentation
1127
+ }
1128
+ end
1129
+ end
1130
+
1131
+ ##
1132
+ # Tries to resolve unmatched aliases when a method or attribute has just
1133
+ # been added.
1134
+
1135
+ def resolve_aliases added
1136
+ # resolve any pending unmatched aliases
1137
+ key = added.pretty_name
1138
+ unmatched_alias_list = @unmatched_alias_lists[key]
1139
+ return unless unmatched_alias_list
1140
+ unmatched_alias_list.each do |unmatched_alias|
1141
+ added.add_alias unmatched_alias, self
1142
+ @external_aliases.delete unmatched_alias
1143
+ end
1144
+ @unmatched_alias_lists.delete key
1145
+ end
1146
+
1147
+ ##
1148
+ # Returns RDoc::Context::Section objects referenced in this context for use
1149
+ # in a table of contents.
1150
+
1151
+ def section_contents
1152
+ used_sections = {}
1153
+
1154
+ each_method do |method|
1155
+ next unless method.display?
1156
+
1157
+ used_sections[method.section] = true
1158
+ end
1159
+
1160
+ # order found sections
1161
+ sections = sort_sections.select do |section|
1162
+ used_sections[section]
1163
+ end
1164
+
1165
+ # only the default section is used
1166
+ return [] if
1167
+ sections.length == 1 and not sections.first.title
1168
+
1169
+ sections
1170
+ end
1171
+
1172
+ ##
1173
+ # Sections in this context
1174
+
1175
+ def sections
1176
+ @sections.values
1177
+ end
1178
+
1179
+ def sections_hash # :nodoc:
1180
+ @sections
1181
+ end
1182
+
1183
+ ##
1184
+ # Sets the current section to a section with +title+. See also #add_section
1185
+
1186
+ def set_current_section title, comment
1187
+ @current_section = add_section title, comment
1188
+ end
1189
+
1190
+ ##
1191
+ # Given an array +methods+ of method names, set the visibility of each to
1192
+ # +visibility+
1193
+
1194
+ def set_visibility_for(methods, visibility, singleton = false)
1195
+ methods_matching methods, singleton do |m|
1196
+ m.visibility = visibility
1197
+ end
1198
+ end
1199
+
1200
+ ##
1201
+ # Given an array +names+ of constants, set the visibility of each constant to
1202
+ # +visibility+
1203
+
1204
+ def set_constant_visibility_for(names, visibility)
1205
+ names.each do |name|
1206
+ constant = @constants_hash[name] or next
1207
+ constant.visibility = visibility
1208
+ end
1209
+ end
1210
+
1211
+ ##
1212
+ # Sorts sections alphabetically (default) or in TomDoc fashion (none,
1213
+ # Public, Internal, Deprecated)
1214
+
1215
+ def sort_sections
1216
+ titles = @sections.map { |title, _| title }
1217
+
1218
+ if titles.length > 1 and
1219
+ TOMDOC_TITLES_SORT ==
1220
+ (titles | TOMDOC_TITLES).sort_by { |title| title.to_s } then
1221
+ @sections.values_at(*TOMDOC_TITLES).compact
1222
+ else
1223
+ @sections.sort_by { |title, _|
1224
+ title.to_s
1225
+ }.map { |_, section|
1226
+ section
1227
+ }
1228
+ end
1229
+ end
1230
+
1231
+ def to_s # :nodoc:
1232
+ "#{self.class.name} #{self.full_name}"
1233
+ end
1234
+
1235
+ ##
1236
+ # Return the TopLevel that owns us
1237
+ #--
1238
+ # FIXME we can be 'owned' by several TopLevel (see #record_location &
1239
+ # #in_files)
1240
+
1241
+ def top_level
1242
+ return @top_level if defined? @top_level
1243
+ @top_level = self
1244
+ @top_level = @top_level.parent until RDoc::TopLevel === @top_level
1245
+ @top_level
1246
+ end
1247
+
1248
+ ##
1249
+ # Upgrades NormalModule +mod+ in +enclosing+ to a +class_type+
1250
+
1251
+ def upgrade_to_class mod, class_type, enclosing
1252
+ enclosing.modules_hash.delete mod.name
1253
+
1254
+ klass = RDoc::ClassModule.from_module class_type, mod
1255
+ klass.store = @store
1256
+
1257
+ # if it was there, then we keep it even if done_documenting
1258
+ @store.classes_hash[mod.full_name] = klass
1259
+ enclosing.classes_hash[mod.name] = klass
1260
+
1261
+ klass
1262
+ end
1263
+
1264
+ autoload :Section, 'rdoc/context/section'
1265
+
1266
+ end