iownbey-rdoc 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/History.txt +13 -0
  2. data/Manifest.txt +61 -0
  3. data/README.txt +34 -0
  4. data/bin/rdoc +22 -0
  5. data/bin/ri +6 -0
  6. data/lib/rdoc.rb +277 -0
  7. data/lib/rdoc/code_objects.rb +776 -0
  8. data/lib/rdoc/diagram.rb +338 -0
  9. data/lib/rdoc/dot.rb +249 -0
  10. data/lib/rdoc/generator.rb +1050 -0
  11. data/lib/rdoc/generator/chm.rb +113 -0
  12. data/lib/rdoc/generator/chm/chm.rb +98 -0
  13. data/lib/rdoc/generator/html.rb +370 -0
  14. data/lib/rdoc/generator/html/hefss.rb +414 -0
  15. data/lib/rdoc/generator/html/html.rb +704 -0
  16. data/lib/rdoc/generator/html/kilmer.rb +418 -0
  17. data/lib/rdoc/generator/html/one_page_html.rb +121 -0
  18. data/lib/rdoc/generator/ri.rb +229 -0
  19. data/lib/rdoc/generator/texinfo.rb +84 -0
  20. data/lib/rdoc/generator/texinfo/class.texinfo.erb +44 -0
  21. data/lib/rdoc/generator/texinfo/file.texinfo.erb +6 -0
  22. data/lib/rdoc/generator/texinfo/method.texinfo.erb +6 -0
  23. data/lib/rdoc/generator/texinfo/texinfo.erb +28 -0
  24. data/lib/rdoc/generator/xml.rb +120 -0
  25. data/lib/rdoc/generator/xml/rdf.rb +113 -0
  26. data/lib/rdoc/generator/xml/xml.rb +111 -0
  27. data/lib/rdoc/markup.rb +473 -0
  28. data/lib/rdoc/markup/attribute_manager.rb +274 -0
  29. data/lib/rdoc/markup/formatter.rb +14 -0
  30. data/lib/rdoc/markup/fragments.rb +337 -0
  31. data/lib/rdoc/markup/inline.rb +101 -0
  32. data/lib/rdoc/markup/lines.rb +152 -0
  33. data/lib/rdoc/markup/preprocess.rb +71 -0
  34. data/lib/rdoc/markup/to_flow.rb +185 -0
  35. data/lib/rdoc/markup/to_html.rb +354 -0
  36. data/lib/rdoc/markup/to_html_crossref.rb +86 -0
  37. data/lib/rdoc/markup/to_latex.rb +328 -0
  38. data/lib/rdoc/markup/to_test.rb +50 -0
  39. data/lib/rdoc/markup/to_texinfo.rb +69 -0
  40. data/lib/rdoc/options.rb +621 -0
  41. data/lib/rdoc/parsers/parse_c.rb +775 -0
  42. data/lib/rdoc/parsers/parse_f95.rb +1841 -0
  43. data/lib/rdoc/parsers/parse_rb.rb +2584 -0
  44. data/lib/rdoc/parsers/parse_simple.rb +40 -0
  45. data/lib/rdoc/parsers/parserfactory.rb +99 -0
  46. data/lib/rdoc/rdoc.rb +277 -0
  47. data/lib/rdoc/ri.rb +4 -0
  48. data/lib/rdoc/ri/cache.rb +188 -0
  49. data/lib/rdoc/ri/descriptions.rb +150 -0
  50. data/lib/rdoc/ri/display.rb +274 -0
  51. data/lib/rdoc/ri/driver.rb +452 -0
  52. data/lib/rdoc/ri/formatter.rb +616 -0
  53. data/lib/rdoc/ri/paths.rb +102 -0
  54. data/lib/rdoc/ri/reader.rb +106 -0
  55. data/lib/rdoc/ri/util.rb +81 -0
  56. data/lib/rdoc/ri/writer.rb +68 -0
  57. data/lib/rdoc/stats.rb +25 -0
  58. data/lib/rdoc/template.rb +64 -0
  59. data/lib/rdoc/tokenstream.rb +33 -0
  60. data/test/test_rdoc_c_parser.rb +261 -0
  61. data/test/test_rdoc_info_formatting.rb +179 -0
  62. data/test/test_rdoc_info_sections.rb +93 -0
  63. data/test/test_rdoc_markup.rb +613 -0
  64. data/test/test_rdoc_markup_attribute_manager.rb +224 -0
  65. data/test/test_rdoc_ri_attribute_formatter.rb +42 -0
  66. data/test/test_rdoc_ri_default_display.rb +295 -0
  67. data/test/test_rdoc_ri_formatter.rb +318 -0
  68. data/test/test_rdoc_ri_overstrike_formatter.rb +69 -0
  69. metadata +142 -0
@@ -0,0 +1,13 @@
1
+ === 2.0.0 / 2008-04-10
2
+
3
+ * 3 Major Enhancements:
4
+ * Renamespaced everything RDoc under the RDoc module.
5
+ * New `ri` implementation.
6
+ * Reads from a cache in ~/.ri/ for enhanced speed.
7
+ * RubyGems aware, only searches latest gem versions.
8
+ * Now up to over 100 tests and 200 assertions.
9
+ * 4 Minor Enhancements:
10
+ * Switched to an ERb-based TemplatePage, see RDoc::TemplatePage.
11
+ * Class/module ri now displays attribute and constant comments.
12
+ * Cross-references can be disabled with a leading \.
13
+ * Relaxed parsing for some RDoc inline markup.
@@ -0,0 +1,61 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ bin/rdoc
6
+ bin/ri
7
+ lib/rdoc.rb
8
+ lib/rdoc/code_objects.rb
9
+ lib/rdoc/diagram.rb
10
+ lib/rdoc/dot.rb
11
+ lib/rdoc/generator.rb
12
+ lib/rdoc/generator/chm.rb
13
+ lib/rdoc/generator/chm/chm.rb
14
+ lib/rdoc/generator/html.rb
15
+ lib/rdoc/generator/html/hefss.rb
16
+ lib/rdoc/generator/html/html.rb
17
+ lib/rdoc/generator/html/kilmer.rb
18
+ lib/rdoc/generator/html/one_page_html.rb
19
+ lib/rdoc/generator/ri.rb
20
+ lib/rdoc/generator/xml.rb
21
+ lib/rdoc/generator/xml/rdf.rb
22
+ lib/rdoc/generator/xml/xml.rb
23
+ lib/rdoc/markup.rb
24
+ lib/rdoc/markup/attribute_manager.rb
25
+ lib/rdoc/markup/formatter.rb
26
+ lib/rdoc/markup/fragments.rb
27
+ lib/rdoc/markup/inline.rb
28
+ lib/rdoc/markup/lines.rb
29
+ lib/rdoc/markup/preprocess.rb
30
+ lib/rdoc/markup/to_flow.rb
31
+ lib/rdoc/markup/to_html.rb
32
+ lib/rdoc/markup/to_html_crossref.rb
33
+ lib/rdoc/markup/to_latex.rb
34
+ lib/rdoc/markup/to_test.rb
35
+ lib/rdoc/options.rb
36
+ lib/rdoc/parsers/parse_c.rb
37
+ lib/rdoc/parsers/parse_f95.rb
38
+ lib/rdoc/parsers/parse_rb.rb
39
+ lib/rdoc/parsers/parse_simple.rb
40
+ lib/rdoc/parsers/parserfactory.rb
41
+ lib/rdoc/rdoc.rb
42
+ lib/rdoc/ri.rb
43
+ lib/rdoc/ri/cache.rb
44
+ lib/rdoc/ri/descriptions.rb
45
+ lib/rdoc/ri/display.rb
46
+ lib/rdoc/ri/driver.rb
47
+ lib/rdoc/ri/formatter.rb
48
+ lib/rdoc/ri/paths.rb
49
+ lib/rdoc/ri/reader.rb
50
+ lib/rdoc/ri/util.rb
51
+ lib/rdoc/ri/writer.rb
52
+ lib/rdoc/stats.rb
53
+ lib/rdoc/template.rb
54
+ lib/rdoc/tokenstream.rb
55
+ test/test_rdoc_c_parser.rb
56
+ test/test_rdoc_markup.rb
57
+ test/test_rdoc_markup_attribute_manager.rb
58
+ test/test_rdoc_ri_attribute_formatter.rb
59
+ test/test_rdoc_ri_default_display.rb
60
+ test/test_rdoc_ri_formatter.rb
61
+ test/test_rdoc_ri_overstrike_formatter.rb
@@ -0,0 +1,34 @@
1
+ = RDoc
2
+
3
+ * http://rubyforge.org/projects/rdoc/
4
+
5
+ == DESCRIPTION:
6
+
7
+ RDoc is an application that produces documentation for one or more Ruby source
8
+ files. RDoc includes the `rdoc` and `ri` tools for generating and displaying
9
+ online documentation.
10
+
11
+ At this point in time, RDoc 2.x is a work in progress and may incur further
12
+ API changes beyond what has been made to the RDoc 1.0.1. Command-line tools
13
+ are largely unaffected, but internal APIs may shift rapidly.
14
+
15
+ == SYNOPSIS:
16
+
17
+ gem 'rdoc'
18
+ require 'rdoc/rdoc'
19
+ # ... see RDoc
20
+
21
+ == BUGS:
22
+
23
+ If you found a bug, please report it at the RDoc project's tracker on
24
+ RubyForge:
25
+
26
+ http://rubyforge.org/tracker/?group_id=627
27
+
28
+ == LICENSE:
29
+
30
+ RDoc is Copyright (c) 2001-2003 Dave Thomas, The Pragmatic Programmers,
31
+ portions (c) 2007-2008 Eric Hodel. It is free software, and may be
32
+ redistributed under the terms specified in the README file of the Ruby
33
+ distribution.
34
+
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # RDoc: Documentation tool for source code
4
+ # (see lib/rdoc/rdoc.rb for more information)
5
+ #
6
+ # Copyright (c) 2003 Dave Thomas
7
+ # Released under the same terms as Ruby
8
+ #
9
+ # $Revision: 15033 $
10
+
11
+ require 'rdoc/rdoc'
12
+
13
+ begin
14
+ r = RDoc::RDoc.new
15
+ r.document ARGV
16
+ rescue Interrupt
17
+ $stderr.puts
18
+ $stderr.puts "Interrupted"
19
+ rescue RDoc::Error => e
20
+ $stderr.puts e.message
21
+ exit 1
22
+ end
data/bin/ri ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr//bin/env ruby
2
+
3
+ require 'rdoc/ri/driver'
4
+
5
+ RDoc::RI::Driver.run ARGV
6
+
@@ -0,0 +1,277 @@
1
+ $DEBUG_RDOC = nil
2
+
3
+ ##
4
+ # = RDOC - Ruby Documentation System
5
+ #
6
+ # This package contains RDoc and RDoc::Markup. RDoc is an application that
7
+ # produces documentation for one or more Ruby source files. We work similarly
8
+ # to JavaDoc, parsing the source, and extracting the definition for classes,
9
+ # modules, and methods (along with includes and requires). We associate with
10
+ # these optional documentation contained in the immediately preceding comment
11
+ # block, and then render the result using a pluggable output formatter.
12
+ # RDoc::Markup is a library that converts plain text into various output
13
+ # formats. The markup library is used to interpret the comment blocks that
14
+ # RDoc uses to document methods, classes, and so on.
15
+ #
16
+ # == Roadmap
17
+ #
18
+ # * If you want to use RDoc to create documentation for your Ruby source files,
19
+ # read on.
20
+ # * If you want to include extensions written in C, see RDoc::C_Parser
21
+ # * For information on the various markups available in comment blocks, see
22
+ # RDoc::Markup.
23
+ # * If you want to drive RDoc programatically, see RDoc::RDoc.
24
+ # * If you want to use the library to format text blocks into HTML, have a look
25
+ # at RDoc::Markup.
26
+ # * If you want to try writing your own HTML output template, see
27
+ # RDoc::Generator::HTML
28
+ #
29
+ # == Summary
30
+ #
31
+ # Once installed, you can create documentation using the 'rdoc' command
32
+ # (the command is 'rdoc.bat' under Windows)
33
+ #
34
+ # % rdoc [options] [names...]
35
+ #
36
+ # Type "rdoc --help" for an up-to-date option summary.
37
+ #
38
+ # A typical use might be to generate documentation for a package of Ruby
39
+ # source (such as rdoc itself).
40
+ #
41
+ # % rdoc
42
+ #
43
+ # This command generates documentation for all the Ruby and C source
44
+ # files in and below the current directory. These will be stored in a
45
+ # documentation tree starting in the subdirectory 'doc'.
46
+ #
47
+ # You can make this slightly more useful for your readers by having the
48
+ # index page contain the documentation for the primary file. In our
49
+ # case, we could type
50
+ #
51
+ # % rdoc --main rdoc.rb
52
+ #
53
+ # You'll find information on the various formatting tricks you can use
54
+ # in comment blocks in the documentation this generates.
55
+ #
56
+ # RDoc uses file extensions to determine how to process each file. File names
57
+ # ending +.rb+ and <tt>.rbw</tt> are assumed to be Ruby source. Files
58
+ # ending +.c+ are parsed as C files. All other files are assumed to
59
+ # contain just Markup-style markup (with or without leading '#' comment
60
+ # markers). If directory names are passed to RDoc, they are scanned
61
+ # recursively for C and Ruby source files only.
62
+ #
63
+ # = Markup
64
+ #
65
+ # For information on how to make lists, hyperlinks, etc. with RDoc, see
66
+ # RDoc::Markup.
67
+ #
68
+ # Comment blocks can be written fairly naturally, either using '#' on
69
+ # successive lines of the comment, or by including the comment in
70
+ # an =begin/=end block. If you use the latter form, the =begin line must be
71
+ # flagged with an RDoc tag:
72
+ #
73
+ # =begin rdoc
74
+ # Documentation to be processed by RDoc.
75
+ #
76
+ # ...
77
+ # =end
78
+ #
79
+ # RDoc stops processing comments if it finds a comment line containing
80
+ # a <tt>--</tt>. This can be used to separate external from internal
81
+ # comments, or to stop a comment being associated with a method, class, or
82
+ # module. Commenting can be turned back on with a line that starts with a
83
+ # <tt>++</tt>.
84
+ #
85
+ # ##
86
+ # # Extract the age and calculate the date-of-birth.
87
+ # #--
88
+ # # FIXME: fails if the birthday falls on February 29th
89
+ # #++
90
+ # # The DOB is returned as a Time object.
91
+ #
92
+ # def get_dob(person)
93
+ # # ...
94
+ # end
95
+ #
96
+ # Names of classes, source files, and any method names containing an
97
+ # underscore or preceded by a hash character are automatically hyperlinked
98
+ # from comment text to their description.
99
+ #
100
+ # Method parameter lists are extracted and displayed with the method
101
+ # description. If a method calls +yield+, then the parameters passed to yield
102
+ # will also be displayed:
103
+ #
104
+ # def fred
105
+ # ...
106
+ # yield line, address
107
+ #
108
+ # This will get documented as:
109
+ #
110
+ # fred() { |line, address| ... }
111
+ #
112
+ # You can override this using a comment containing ':yields: ...' immediately
113
+ # after the method definition
114
+ #
115
+ # def fred # :yields: index, position
116
+ # # ...
117
+ #
118
+ # yield line, address
119
+ #
120
+ # which will get documented as
121
+ #
122
+ # fred() { |index, position| ... }
123
+ #
124
+ # +:yields:+ is an example of a documentation directive. These appear
125
+ # immediately after the start of the document element they are modifying.
126
+ #
127
+ # == Directives
128
+ #
129
+ # [+:nodoc:+ / +:nodoc:+ all]
130
+ # Don't include this element in the documentation. For classes
131
+ # and modules, the methods, aliases, constants, and attributes
132
+ # directly within the affected class or module will also be
133
+ # omitted. By default, though, modules and classes within that
134
+ # class of module _will_ be documented. This is turned off by
135
+ # adding the +all+ modifier.
136
+ #
137
+ # module MyModule # :nodoc:
138
+ # class Input
139
+ # end
140
+ # end
141
+ #
142
+ # module OtherModule # :nodoc: all
143
+ # class Output
144
+ # end
145
+ # end
146
+ #
147
+ # In the above code, only class +MyModule::Input+ will be documented.
148
+ # :nodoc: is global across all files the class or module appears in, so use
149
+ # :stopdoc:/:startdoc: to only omit documentation for a particular set of
150
+ # methods, etc.
151
+ #
152
+ # [+:doc:+]
153
+ # Force a method or attribute to be documented even if it wouldn't otherwise
154
+ # be. Useful if, for example, you want to include documentation of a
155
+ # particular private method.
156
+ #
157
+ # [+:notnew:+]
158
+ # Only applicable to the +initialize+ instance method. Normally RDoc
159
+ # assumes that the documentation and parameters for #initialize are
160
+ # actually for the ::new method, and so fakes out a ::new for the class.
161
+ # The :notnew: modifier stops this. Remember that #initialize is protected,
162
+ # so you won't see the documentation unless you use the -a command line
163
+ # option.
164
+ #
165
+ # Comment blocks can contain other directives:
166
+ #
167
+ # [<tt>:section: title</tt>]
168
+ # Starts a new section in the output. The title following +:section:+ is
169
+ # used as the section heading, and the remainder of the comment containing
170
+ # the section is used as introductory text. Subsequent methods, aliases,
171
+ # attributes, and classes will be documented in this section. A :section:
172
+ # comment block may have one or more lines before the :section: directive.
173
+ # These will be removed, and any identical lines at the end of the block are
174
+ # also removed. This allows you to add visual cues such as:
175
+ #
176
+ # # ----------------------------------------
177
+ # # :section: My Section
178
+ # # This is the section that I wrote.
179
+ # # See it glisten in the noon-day sun.
180
+ # # ----------------------------------------
181
+ #
182
+ # [+:call-seq:+]
183
+ # Lines up to the next blank line in the comment are treated as the method's
184
+ # calling sequence, overriding the default parsing of method parameters and
185
+ # yield arguments.
186
+ #
187
+ # [+:include:+ _filename_]
188
+ # \Include the contents of the named file at this point. The file will be
189
+ # searched for in the directories listed by the +--include+ option, or in
190
+ # the current directory by default. The contents of the file will be
191
+ # shifted to have the same indentation as the ':' at the start of the
192
+ # :include: directive.
193
+ #
194
+ # [+:title:+ _text_]
195
+ # Sets the title for the document. Equivalent to the <tt>--title</tt>
196
+ # command line parameter. (The command line parameter overrides any :title:
197
+ # directive in the source).
198
+ #
199
+ # [+:enddoc:+]
200
+ # Document nothing further at the current level.
201
+ #
202
+ # [+:main:+ _name_]
203
+ # Equivalent to the <tt>--main</tt> command line parameter.
204
+ #
205
+ # [+:stopdoc:+ / +:startdoc:+]
206
+ # Stop and start adding new documentation elements to the current container.
207
+ # For example, if a class has a number of constants that you don't want to
208
+ # document, put a +:stopdoc:+ before the first, and a +:startdoc:+ after the
209
+ # last. If you don't specifiy a +:startdoc:+ by the end of the container,
210
+ # disables documentation for the entire class or module.
211
+ #
212
+ # = Other stuff
213
+ #
214
+ # RDoc is currently being maintained by Eric Hodel <drbrain@segment7.net>
215
+ #
216
+ # Dave Thomas <dave@pragmaticprogrammer.com> is the original author of RDoc.
217
+ #
218
+ # == Credits
219
+ #
220
+ # * The Ruby parser in rdoc/parse.rb is based heavily on the outstanding
221
+ # work of Keiju ISHITSUKA of Nippon Rational Inc, who produced the Ruby
222
+ # parser for irb and the rtags package.
223
+ #
224
+ # * Code to diagram classes and modules was written by Sergey A Yanovitsky
225
+ # (Jah) of Enticla.
226
+ #
227
+ # * Charset patch from MoonWolf.
228
+ #
229
+ # * Rich Kilmer wrote the kilmer.rb output template.
230
+ #
231
+ # * Dan Brickley led the design of the RDF format.
232
+ #
233
+ # == License
234
+ #
235
+ # RDoc is Copyright (c) 2001-2003 Dave Thomas, The Pragmatic Programmers. It
236
+ # is free software, and may be redistributed under the terms specified
237
+ # in the README file of the Ruby distribution.
238
+ #
239
+ # == Warranty
240
+ #
241
+ # This software is provided "as is" and without any express or implied
242
+ # warranties, including, without limitation, the implied warranties of
243
+ # merchantibility and fitness for a particular purpose.
244
+
245
+ module RDoc
246
+
247
+ ##
248
+ # Exception thrown by any rdoc error.
249
+
250
+ class Error < RuntimeError; end
251
+
252
+ RDocError = Error # :nodoc:
253
+
254
+ ##
255
+ # RDoc version you are using
256
+
257
+ VERSION = "2.0.0"
258
+
259
+ ##
260
+ # Name of the dotfile that contains the description of files to be processed
261
+ # in the current directory
262
+
263
+ DOT_DOC_FILENAME = ".document"
264
+
265
+ GENERAL_MODIFIERS = %w[nodoc].freeze
266
+
267
+ CLASS_MODIFIERS = GENERAL_MODIFIERS
268
+
269
+ ATTR_MODIFIERS = GENERAL_MODIFIERS
270
+
271
+ CONSTANT_MODIFIERS = GENERAL_MODIFIERS
272
+
273
+ METHOD_MODIFIERS = GENERAL_MODIFIERS +
274
+ %w[arg args yield yields notnew not-new not_new doc]
275
+
276
+ end
277
+
@@ -0,0 +1,776 @@
1
+ # We represent the various high-level code constructs that appear
2
+ # in Ruby programs: classes, modules, methods, and so on.
3
+
4
+ require 'rdoc/tokenstream'
5
+
6
+ module RDoc
7
+
8
+ ##
9
+ # We contain the common stuff for contexts (which are containers)
10
+ # and other elements (methods, attributes and so on)
11
+
12
+ class CodeObject
13
+
14
+ attr_accessor :parent
15
+
16
+ # We are the model of the code, but we know that at some point
17
+ # we will be worked on by viewers. By implementing the Viewable
18
+ # protocol, viewers can associated themselves with these objects.
19
+
20
+ attr_accessor :viewer
21
+
22
+ # are we done documenting (ie, did we come across a :enddoc:)?
23
+
24
+ attr_accessor :done_documenting
25
+
26
+ # Which section are we in
27
+
28
+ attr_accessor :section
29
+
30
+ # do we document ourselves?
31
+
32
+ attr_reader :document_self
33
+
34
+ def document_self=(val)
35
+ @document_self = val
36
+ if !val
37
+ remove_methods_etc
38
+ end
39
+ end
40
+
41
+ # set and cleared by :startdoc: and :enddoc:, this is used to toggle
42
+ # the capturing of documentation
43
+ def start_doc
44
+ @document_self = true
45
+ @document_children = true
46
+ end
47
+
48
+ def stop_doc
49
+ @document_self = false
50
+ @document_children = false
51
+ end
52
+
53
+ # do we document ourselves and our children
54
+
55
+ attr_reader :document_children
56
+
57
+ def document_children=(val)
58
+ @document_children = val
59
+ if !val
60
+ remove_classes_and_modules
61
+ end
62
+ end
63
+
64
+ # Do we _force_ documentation, even is we wouldn't normally show the entity
65
+ attr_accessor :force_documentation
66
+
67
+ # Default callbacks to nothing, but this is overridden for classes
68
+ # and modules
69
+ def remove_classes_and_modules
70
+ end
71
+
72
+ def remove_methods_etc
73
+ end
74
+
75
+ def initialize
76
+ @document_self = true
77
+ @document_children = true
78
+ @force_documentation = false
79
+ @done_documenting = false
80
+ end
81
+
82
+ # Access the code object's comment
83
+ attr_reader :comment
84
+
85
+ # Update the comment, but don't overwrite a real comment with an empty one
86
+ def comment=(comment)
87
+ @comment = comment unless comment.empty?
88
+ end
89
+
90
+ # There's a wee trick we pull. Comment blocks can have directives that
91
+ # override the stuff we extract during the parse. So, we have a special
92
+ # class method, attr_overridable, that lets code objects list
93
+ # those directives. Wehn a comment is assigned, we then extract
94
+ # out any matching directives and update our object
95
+
96
+ def self.attr_overridable(name, *aliases)
97
+ @overridables ||= {}
98
+
99
+ attr_accessor name
100
+
101
+ aliases.unshift name
102
+ aliases.each do |directive_name|
103
+ @overridables[directive_name.to_s] = name
104
+ end
105
+ end
106
+
107
+ end
108
+
109
+ # A Context is something that can hold modules, classes, methods,
110
+ # attributes, aliases, requires, and includes. Classes, modules, and
111
+ # files are all Contexts.
112
+
113
+ class Context < CodeObject
114
+ attr_reader :name, :method_list, :attributes, :aliases, :constants
115
+ attr_reader :requires, :includes, :in_files, :visibility
116
+
117
+ attr_reader :sections
118
+
119
+ class Section
120
+ attr_reader :title, :comment, :sequence
121
+
122
+ @@sequence = "SEC00000"
123
+
124
+ def initialize(title, comment)
125
+ @title = title
126
+ @@sequence.succ!
127
+ @sequence = @@sequence.dup
128
+ @comment = nil
129
+ set_comment(comment)
130
+ end
131
+
132
+ private
133
+
134
+ # Set the comment for this section from the original comment block
135
+ # If the first line contains :section:, strip it and use the rest. Otherwise
136
+ # remove lines up to the line containing :section:, and look for
137
+ # those lines again at the end and remove them. This lets us write
138
+ #
139
+ # # ---------------------
140
+ # # :SECTION: The title
141
+ # # The body
142
+ # # ---------------------
143
+
144
+ def set_comment(comment)
145
+ return unless comment
146
+
147
+ if comment =~ /^.*?:section:.*$/
148
+ start = $`
149
+ rest = $'
150
+ if start.empty?
151
+ @comment = rest
152
+ else
153
+ @comment = rest.sub(/#{start.chomp}\Z/, '')
154
+ end
155
+ else
156
+ @comment = comment
157
+ end
158
+ @comment = nil if @comment.empty?
159
+ end
160
+ end
161
+
162
+
163
+ def initialize
164
+ super()
165
+
166
+ @in_files = []
167
+
168
+ @name ||= "unknown"
169
+ @comment ||= ""
170
+ @parent = nil
171
+ @visibility = :public
172
+
173
+ @current_section = Section.new(nil, nil)
174
+ @sections = [ @current_section ]
175
+
176
+ initialize_methods_etc
177
+ initialize_classes_and_modules
178
+ end
179
+
180
+ # map the class hash to an array externally
181
+ def classes
182
+ @classes.values
183
+ end
184
+
185
+ # map the module hash to an array externally
186
+ def modules
187
+ @modules.values
188
+ end
189
+
190
+ # Change the default visibility for new methods
191
+ def ongoing_visibility=(vis)
192
+ @visibility = vis
193
+ end
194
+
195
+ # Given an array +methods+ of method names, set the
196
+ # visibility of the corresponding AnyMethod object
197
+
198
+ def set_visibility_for(methods, vis, singleton=false)
199
+ count = 0
200
+ @method_list.each do |m|
201
+ if methods.include?(m.name) && m.singleton == singleton
202
+ m.visibility = vis
203
+ count += 1
204
+ end
205
+ end
206
+
207
+ return if count == methods.size || singleton
208
+
209
+ # perhaps we need to look at attributes
210
+
211
+ @attributes.each do |a|
212
+ if methods.include?(a.name)
213
+ a.visibility = vis
214
+ count += 1
215
+ end
216
+ end
217
+ end
218
+
219
+ # Record the file that we happen to find it in
220
+ def record_location(toplevel)
221
+ @in_files << toplevel unless @in_files.include?(toplevel)
222
+ end
223
+
224
+ # Return true if at least part of this thing was defined in +file+
225
+ def defined_in?(file)
226
+ @in_files.include?(file)
227
+ end
228
+
229
+ def add_class(class_type, name, superclass)
230
+ add_class_or_module(@classes, class_type, name, superclass)
231
+ end
232
+
233
+ def add_module(class_type, name)
234
+ add_class_or_module(@modules, class_type, name, nil)
235
+ end
236
+
237
+ def add_method(a_method)
238
+ puts "Adding #@visibility method #{a_method.name} to #@name" if $DEBUG_RDOC
239
+ a_method.visibility = @visibility
240
+ add_to(@method_list, a_method)
241
+ end
242
+
243
+ def add_attribute(an_attribute)
244
+ add_to(@attributes, an_attribute)
245
+ end
246
+
247
+ def add_alias(an_alias)
248
+ meth = find_instance_method_named(an_alias.old_name)
249
+ if meth
250
+ new_meth = AnyMethod.new(an_alias.text, an_alias.new_name)
251
+ new_meth.is_alias_for = meth
252
+ new_meth.singleton = meth.singleton
253
+ new_meth.params = meth.params
254
+ new_meth.comment = "Alias for \##{meth.name}"
255
+ meth.add_alias(new_meth)
256
+ add_method(new_meth)
257
+ else
258
+ add_to(@aliases, an_alias)
259
+ end
260
+ end
261
+
262
+ def add_include(an_include)
263
+ add_to(@includes, an_include)
264
+ end
265
+
266
+ def add_constant(const)
267
+ add_to(@constants, const)
268
+ end
269
+
270
+ # Requires always get added to the top-level (file) context
271
+ def add_require(a_require)
272
+ if self.kind_of? TopLevel
273
+ add_to(@requires, a_require)
274
+ else
275
+ parent.add_require(a_require)
276
+ end
277
+ end
278
+
279
+ def add_class_or_module(collection, class_type, name, superclass=nil)
280
+ cls = collection[name]
281
+ if cls
282
+ puts "Reusing class/module #{name}" if $DEBUG_RDOC
283
+ else
284
+ cls = class_type.new(name, superclass)
285
+ puts "Adding class/module #{name} to #@name" if $DEBUG_RDOC
286
+ # collection[name] = cls if @document_self && !@done_documenting
287
+ collection[name] = cls if !@done_documenting
288
+ cls.parent = self
289
+ cls.section = @current_section
290
+ end
291
+ cls
292
+ end
293
+
294
+ def add_to(array, thing)
295
+ array << thing if @document_self && !@done_documenting
296
+ thing.parent = self
297
+ thing.section = @current_section
298
+ end
299
+
300
+ # If a class's documentation is turned off after we've started
301
+ # collecting methods etc., we need to remove the ones
302
+ # we have
303
+
304
+ def remove_methods_etc
305
+ initialize_methods_etc
306
+ end
307
+
308
+ def initialize_methods_etc
309
+ @method_list = []
310
+ @attributes = []
311
+ @aliases = []
312
+ @requires = []
313
+ @includes = []
314
+ @constants = []
315
+ end
316
+
317
+ # and remove classes and modules when we see a :nodoc: all
318
+ def remove_classes_and_modules
319
+ initialize_classes_and_modules
320
+ end
321
+
322
+ def initialize_classes_and_modules
323
+ @classes = {}
324
+ @modules = {}
325
+ end
326
+
327
+ # Find a named module
328
+ def find_module_named(name)
329
+ return self if self.name == name
330
+ res = @modules[name] || @classes[name]
331
+ return res if res
332
+ find_enclosing_module_named(name)
333
+ end
334
+
335
+ # find a module at a higher scope
336
+ def find_enclosing_module_named(name)
337
+ parent && parent.find_module_named(name)
338
+ end
339
+
340
+ # Iterate over all the classes and modules in
341
+ # this object
342
+
343
+ def each_classmodule
344
+ @modules.each_value {|m| yield m}
345
+ @classes.each_value {|c| yield c}
346
+ end
347
+
348
+ def each_method
349
+ @method_list.each {|m| yield m}
350
+ end
351
+
352
+ def each_attribute
353
+ @attributes.each {|a| yield a}
354
+ end
355
+
356
+ def each_constant
357
+ @constants.each {|c| yield c}
358
+ end
359
+
360
+ # Return the toplevel that owns us
361
+
362
+ def toplevel
363
+ return @toplevel if defined? @toplevel
364
+ @toplevel = self
365
+ @toplevel = @toplevel.parent until TopLevel === @toplevel
366
+ @toplevel
367
+ end
368
+
369
+ # allow us to sort modules by name
370
+ def <=>(other)
371
+ name <=> other.name
372
+ end
373
+
374
+ # Look up the given symbol. If method is non-nil, then
375
+ # we assume the symbol references a module that
376
+ # contains that method
377
+ def find_symbol(symbol, method=nil)
378
+ result = nil
379
+ case symbol
380
+ when /^::(.*)/
381
+ result = toplevel.find_symbol($1)
382
+ when /::/
383
+ modules = symbol.split(/::/)
384
+ unless modules.empty?
385
+ module_name = modules.shift
386
+ result = find_module_named(module_name)
387
+ if result
388
+ modules.each do |name|
389
+ result = result.find_module_named(name)
390
+ break unless result
391
+ end
392
+ end
393
+ end
394
+ else
395
+ # if a method is specified, then we're definitely looking for
396
+ # a module, otherwise it could be any symbol
397
+ if method
398
+ result = find_module_named(symbol)
399
+ else
400
+ result = find_local_symbol(symbol)
401
+ if result.nil?
402
+ if symbol =~ /^[A-Z]/
403
+ result = parent
404
+ while result && result.name != symbol
405
+ result = result.parent
406
+ end
407
+ end
408
+ end
409
+ end
410
+ end
411
+ if result && method
412
+ if !result.respond_to?(:find_local_symbol)
413
+ #p result.name
414
+ #p method
415
+ fail
416
+ end
417
+ result = result.find_local_symbol(method)
418
+ end
419
+ result
420
+ end
421
+
422
+ def find_local_symbol(symbol)
423
+ res = find_method_named(symbol) ||
424
+ find_constant_named(symbol) ||
425
+ find_attribute_named(symbol) ||
426
+ find_module_named(symbol)
427
+ end
428
+
429
+ # Handle sections
430
+
431
+ def set_current_section(title, comment)
432
+ @current_section = Section.new(title, comment)
433
+ @sections << @current_section
434
+ end
435
+
436
+ private
437
+
438
+ # Find a named method, or return nil
439
+ def find_method_named(name)
440
+ @method_list.find {|meth| meth.name == name}
441
+ end
442
+
443
+ # Find a named instance method, or return nil
444
+ def find_instance_method_named(name)
445
+ @method_list.find {|meth| meth.name == name && !meth.singleton}
446
+ end
447
+
448
+ # Find a named constant, or return nil
449
+ def find_constant_named(name)
450
+ @constants.find {|m| m.name == name}
451
+ end
452
+
453
+ # Find a named attribute, or return nil
454
+ def find_attribute_named(name)
455
+ @attributes.find {|m| m.name == name}
456
+ end
457
+
458
+ end
459
+
460
+ ##
461
+ # A TopLevel context is a source file
462
+
463
+ class TopLevel < Context
464
+ attr_accessor :file_stat
465
+ attr_accessor :file_relative_name
466
+ attr_accessor :file_absolute_name
467
+ attr_accessor :diagram
468
+
469
+ @@all_classes = {}
470
+ @@all_modules = {}
471
+
472
+ def self.reset
473
+ @@all_classes = {}
474
+ @@all_modules = {}
475
+ end
476
+
477
+ def initialize(file_name)
478
+ super()
479
+ @name = "TopLevel"
480
+ @file_relative_name = file_name
481
+ @file_absolute_name = file_name
482
+ @file_stat = File.stat(file_name)
483
+ @diagram = nil
484
+ end
485
+
486
+ def full_name
487
+ nil
488
+ end
489
+
490
+ ##
491
+ # Adding a class or module to a TopLevel is special, as we only want one
492
+ # copy of a particular top-level class. For example, if both file A and
493
+ # file B implement class C, we only want one ClassModule object for C.
494
+ # This code arranges to share classes and modules between files.
495
+
496
+ def add_class_or_module(collection, class_type, name, superclass)
497
+ cls = collection[name]
498
+
499
+ if cls
500
+ puts "Reusing class/module #{name}" if $DEBUG_RDOC
501
+ else
502
+ if class_type == NormalModule
503
+ all = @@all_modules
504
+ else
505
+ all = @@all_classes
506
+ end
507
+
508
+ cls = all[name]
509
+
510
+ if !cls
511
+ cls = class_type.new(name, superclass)
512
+ all[name] = cls unless @done_documenting
513
+ end
514
+
515
+ puts "Adding class/module #{name} to #{@name}" if $DEBUG_RDOC
516
+
517
+ collection[name] = cls unless @done_documenting
518
+
519
+ cls.parent = self
520
+ end
521
+
522
+ cls
523
+ end
524
+
525
+ def self.all_classes_and_modules
526
+ @@all_classes.values + @@all_modules.values
527
+ end
528
+
529
+ def self.find_class_named(name)
530
+ @@all_classes.each_value do |c|
531
+ res = c.find_class_named(name)
532
+ return res if res
533
+ end
534
+ nil
535
+ end
536
+
537
+ def find_local_symbol(symbol)
538
+ find_class_or_module_named(symbol) || super
539
+ end
540
+
541
+ def find_class_or_module_named(symbol)
542
+ @@all_classes.each_value {|c| return c if c.name == symbol}
543
+ @@all_modules.each_value {|m| return m if m.name == symbol}
544
+ nil
545
+ end
546
+
547
+ ##
548
+ # Find a named module
549
+
550
+ def find_module_named(name)
551
+ find_class_or_module_named(name) || find_enclosing_module_named(name)
552
+ end
553
+
554
+ end
555
+
556
+ # ClassModule is the base class for objects representing either a
557
+ # class or a module.
558
+
559
+ class ClassModule < Context
560
+
561
+ attr_reader :superclass
562
+ attr_accessor :diagram
563
+
564
+ def initialize(name, superclass = nil)
565
+ @name = name
566
+ @diagram = nil
567
+ @superclass = superclass
568
+ @comment = ""
569
+ super()
570
+ end
571
+
572
+ # Return the fully qualified name of this class or module
573
+ def full_name
574
+ if @parent && @parent.full_name
575
+ @parent.full_name + "::" + @name
576
+ else
577
+ @name
578
+ end
579
+ end
580
+
581
+ def http_url(prefix)
582
+ path = full_name.split("::")
583
+ File.join(prefix, *path) + ".html"
584
+ end
585
+
586
+ # Return +true+ if this object represents a module
587
+ def is_module?
588
+ false
589
+ end
590
+
591
+ # to_s is simply for debugging
592
+ def to_s
593
+ res = self.class.name + ": " + @name
594
+ res << @comment.to_s
595
+ res << super
596
+ res
597
+ end
598
+
599
+ def find_class_named(name)
600
+ return self if full_name == name
601
+ @classes.each_value {|c| return c if c.find_class_named(name) }
602
+ nil
603
+ end
604
+ end
605
+
606
+ # Anonymous classes
607
+ class AnonClass < ClassModule
608
+ end
609
+
610
+ # Normal classes
611
+ class NormalClass < ClassModule
612
+ end
613
+
614
+ # Singleton classes
615
+ class SingleClass < ClassModule
616
+ end
617
+
618
+ # Module
619
+ class NormalModule < ClassModule
620
+ def is_module?
621
+ true
622
+ end
623
+ end
624
+
625
+ ##
626
+ # AnyMethod is the base class for objects representing methods
627
+
628
+ class AnyMethod < CodeObject
629
+ attr_accessor :name
630
+ attr_accessor :visibility
631
+ attr_accessor :block_params
632
+ attr_accessor :dont_rename_initialize
633
+ attr_accessor :singleton
634
+ attr_reader :text
635
+
636
+ # list of other names for this method
637
+ attr_reader :aliases
638
+
639
+ # method we're aliasing
640
+ attr_accessor :is_alias_for
641
+
642
+ attr_overridable :params, :param, :parameters, :parameter
643
+
644
+ attr_accessor :call_seq
645
+
646
+ include TokenStream
647
+
648
+ def initialize(text, name)
649
+ super()
650
+ @text = text
651
+ @name = name
652
+ @token_stream = nil
653
+ @visibility = :public
654
+ @dont_rename_initialize = false
655
+ @block_params = nil
656
+ @aliases = []
657
+ @is_alias_for = nil
658
+ @comment = ""
659
+ @call_seq = nil
660
+ end
661
+
662
+ def <=>(other)
663
+ @name <=> other.name
664
+ end
665
+
666
+ def to_s
667
+ res = self.class.name + ": " + @name + " (" + @text + ")\n"
668
+ res << @comment.to_s
669
+ res
670
+ end
671
+
672
+ def param_seq
673
+ p = params.gsub(/\s*\#.*/, '')
674
+ p = p.tr("\n", " ").squeeze(" ")
675
+ p = "(" + p + ")" unless p[0] == ?(
676
+
677
+ if (block = block_params)
678
+ # If this method has explicit block parameters, remove any
679
+ # explicit &block
680
+ $stderr.puts p
681
+ p.sub!(/,?\s*&\w+/)
682
+ $stderr.puts p
683
+
684
+ block.gsub!(/\s*\#.*/, '')
685
+ block = block.tr("\n", " ").squeeze(" ")
686
+ if block[0] == ?(
687
+ block.sub!(/^\(/, '').sub!(/\)/, '')
688
+ end
689
+ p << " {|#{block}| ...}"
690
+ end
691
+ p
692
+ end
693
+
694
+ def add_alias(method)
695
+ @aliases << method
696
+ end
697
+ end
698
+
699
+ # Represent an alias, which is an old_name/ new_name pair associated
700
+ # with a particular context
701
+ class Alias < CodeObject
702
+ attr_accessor :text, :old_name, :new_name, :comment
703
+
704
+ def initialize(text, old_name, new_name, comment)
705
+ super()
706
+ @text = text
707
+ @old_name = old_name
708
+ @new_name = new_name
709
+ self.comment = comment
710
+ end
711
+
712
+ def to_s
713
+ "alias: #{self.old_name} -> #{self.new_name}\n#{self.comment}"
714
+ end
715
+ end
716
+
717
+ # Represent a constant
718
+ class Constant < CodeObject
719
+ attr_accessor :name, :value
720
+
721
+ def initialize(name, value, comment)
722
+ super()
723
+ @name = name
724
+ @value = value
725
+ self.comment = comment
726
+ end
727
+ end
728
+
729
+ # Represent attributes
730
+ class Attr < CodeObject
731
+ attr_accessor :text, :name, :rw, :visibility
732
+
733
+ def initialize(text, name, rw, comment)
734
+ super()
735
+ @text = text
736
+ @name = name
737
+ @rw = rw
738
+ @visibility = :public
739
+ self.comment = comment
740
+ end
741
+
742
+ def to_s
743
+ "attr: #{self.name} #{self.rw}\n#{self.comment}"
744
+ end
745
+
746
+ def <=>(other)
747
+ self.name <=> other.name
748
+ end
749
+ end
750
+
751
+ # a required file
752
+
753
+ class Require < CodeObject
754
+ attr_accessor :name
755
+
756
+ def initialize(name, comment)
757
+ super()
758
+ @name = name.gsub(/'|"/, "") #'
759
+ self.comment = comment
760
+ end
761
+
762
+ end
763
+
764
+ # an included module
765
+ class Include < CodeObject
766
+ attr_accessor :name
767
+
768
+ def initialize(name, comment)
769
+ super()
770
+ @name = name
771
+ self.comment = comment
772
+ end
773
+
774
+ end
775
+
776
+ end