gitlab-rdoc 6.3.2

Sign up to get free protection for your applications and to get access to all the features.
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