rdoc 2.5.11 → 3.0

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

Potentially problematic release.


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

Files changed (113) hide show
  1. data.tar.gz.sig +0 -0
  2. data/.document +1 -0
  3. data/History.txt +95 -0
  4. data/Manifest.txt +13 -4
  5. data/README.txt +9 -3
  6. data/Rakefile +1 -1
  7. data/lib/rdoc.rb +15 -298
  8. data/lib/rdoc/alias.rb +65 -16
  9. data/lib/rdoc/any_method.rb +27 -150
  10. data/lib/rdoc/attr.rb +36 -115
  11. data/lib/rdoc/class_module.rb +236 -22
  12. data/lib/rdoc/code_object.rb +76 -31
  13. data/lib/rdoc/constant.rb +32 -4
  14. data/lib/rdoc/context.rb +494 -222
  15. data/lib/rdoc/encoding.rb +79 -0
  16. data/lib/rdoc/erbio.rb +37 -0
  17. data/lib/rdoc/gauntlet.rb +9 -5
  18. data/lib/rdoc/generator.rb +33 -1
  19. data/lib/rdoc/generator/darkfish.rb +284 -375
  20. data/lib/rdoc/generator/markup.rb +72 -36
  21. data/lib/rdoc/generator/ri.rb +4 -4
  22. data/lib/rdoc/generator/template/darkfish/classpage.rhtml +267 -274
  23. data/lib/rdoc/generator/template/darkfish/filepage.rhtml +91 -91
  24. data/lib/rdoc/generator/template/darkfish/index.rhtml +45 -45
  25. data/lib/rdoc/generator/template/darkfish/rdoc.css +298 -298
  26. data/lib/rdoc/include.rb +40 -1
  27. data/lib/rdoc/known_classes.rb +1 -0
  28. data/lib/rdoc/markup.rb +467 -2
  29. data/lib/rdoc/markup/attribute_manager.rb +24 -6
  30. data/lib/rdoc/markup/blank_line.rb +11 -3
  31. data/lib/rdoc/markup/document.rb +6 -0
  32. data/lib/rdoc/markup/formatter.rb +10 -0
  33. data/lib/rdoc/markup/formatter_test_case.rb +339 -3
  34. data/lib/rdoc/markup/heading.rb +3 -0
  35. data/lib/rdoc/markup/inline.rb +11 -1
  36. data/lib/rdoc/markup/list.rb +3 -0
  37. data/lib/rdoc/markup/list_item.rb +3 -0
  38. data/lib/rdoc/markup/paragraph.rb +3 -0
  39. data/lib/rdoc/markup/parser.rb +191 -237
  40. data/lib/rdoc/markup/{preprocess.rb → pre_process.rb} +50 -29
  41. data/lib/rdoc/markup/raw.rb +4 -0
  42. data/lib/rdoc/markup/rule.rb +3 -0
  43. data/lib/rdoc/markup/text_formatter_test_case.rb +116 -0
  44. data/lib/rdoc/markup/to_ansi.rb +14 -2
  45. data/lib/rdoc/markup/to_bs.rb +8 -2
  46. data/lib/rdoc/markup/to_html.rb +84 -91
  47. data/lib/rdoc/markup/to_html_crossref.rb +77 -26
  48. data/lib/rdoc/markup/to_rdoc.rb +94 -49
  49. data/lib/rdoc/markup/to_test.rb +9 -1
  50. data/lib/rdoc/markup/verbatim.rb +6 -3
  51. data/lib/rdoc/method_attr.rb +353 -0
  52. data/lib/rdoc/normal_class.rb +11 -2
  53. data/lib/rdoc/normal_module.rb +0 -5
  54. data/lib/rdoc/options.rb +373 -82
  55. data/lib/rdoc/parser.rb +59 -23
  56. data/lib/rdoc/parser/c.rb +224 -86
  57. data/lib/rdoc/parser/ruby.rb +219 -111
  58. data/lib/rdoc/parser/ruby_tools.rb +4 -1
  59. data/lib/rdoc/parser/simple.rb +9 -4
  60. data/lib/rdoc/rdoc.rb +68 -28
  61. data/lib/rdoc/require.rb +21 -0
  62. data/lib/rdoc/ri/driver.rb +20 -10
  63. data/lib/rdoc/ri/paths.rb +2 -2
  64. data/lib/rdoc/ri/store.rb +22 -5
  65. data/lib/rdoc/ruby_lex.rb +11 -12
  66. data/lib/rdoc/ruby_token.rb +2 -2
  67. data/lib/rdoc/single_class.rb +2 -1
  68. data/lib/rdoc/stats.rb +202 -162
  69. data/lib/rdoc/stats/normal.rb +51 -0
  70. data/lib/rdoc/stats/quiet.rb +59 -0
  71. data/lib/rdoc/stats/verbose.rb +45 -0
  72. data/lib/rdoc/text.rb +133 -4
  73. data/lib/rdoc/{tokenstream.rb → token_stream.rb} +0 -2
  74. data/lib/rdoc/top_level.rb +230 -39
  75. data/test/test_attribute_manager.rb +58 -7
  76. data/test/test_rdoc_alias.rb +13 -0
  77. data/test/test_rdoc_any_method.rb +43 -2
  78. data/test/test_rdoc_attr.rb +15 -8
  79. data/test/test_rdoc_class_module.rb +133 -0
  80. data/test/test_rdoc_code_object.rb +62 -5
  81. data/test/test_rdoc_context.rb +72 -26
  82. data/test/test_rdoc_encoding.rb +145 -0
  83. data/test/test_rdoc_generator_darkfish.rb +119 -0
  84. data/test/test_rdoc_generator_ri.rb +22 -2
  85. data/test/test_rdoc_include.rb +79 -0
  86. data/test/test_rdoc_markup_attribute_manager.rb +4 -4
  87. data/test/test_rdoc_markup_parser.rb +134 -95
  88. data/test/test_rdoc_markup_pre_process.rb +7 -2
  89. data/test/test_rdoc_markup_to_ansi.rb +43 -153
  90. data/test/test_rdoc_markup_to_bs.rb +42 -156
  91. data/test/test_rdoc_markup_to_html.rb +130 -58
  92. data/test/test_rdoc_markup_to_html_crossref.rb +10 -10
  93. data/test/test_rdoc_markup_to_rdoc.rb +40 -151
  94. data/test/test_rdoc_method_attr.rb +122 -0
  95. data/test/test_rdoc_normal_class.rb +1 -1
  96. data/test/test_rdoc_normal_module.rb +6 -1
  97. data/test/test_rdoc_options.rb +237 -12
  98. data/test/test_rdoc_parser.rb +3 -22
  99. data/test/test_rdoc_parser_c.rb +203 -2
  100. data/test/test_rdoc_parser_ruby.rb +403 -89
  101. data/test/test_rdoc_parser_simple.rb +25 -1
  102. data/test/test_rdoc_rdoc.rb +44 -32
  103. data/test/test_rdoc_ri_driver.rb +29 -24
  104. data/test/test_rdoc_ri_store.rb +46 -3
  105. data/test/test_rdoc_task.rb +1 -1
  106. data/test/test_rdoc_text.rb +102 -8
  107. data/test/test_rdoc_top_level.rb +13 -4
  108. data/test/xref_data.rb +8 -0
  109. data/test/xref_test_case.rb +6 -0
  110. metadata +29 -19
  111. metadata.gz.sig +0 -0
  112. data/lib/rdoc/parser/perl.rb +0 -165
  113. data/test/test_rdoc_parser_perl.rb +0 -73
@@ -8,31 +8,114 @@ class RDoc::ClassModule < RDoc::Context
8
8
 
9
9
  MARSHAL_VERSION = 0 # :nodoc:
10
10
 
11
- attr_accessor :diagram
11
+ ##
12
+ # Constants that are aliases for this class or module
13
+
14
+ attr_accessor :constant_aliases
15
+
16
+ attr_accessor :diagram # :nodoc:
12
17
 
13
18
  ##
14
- # Creates a new ClassModule with +name+ with optional +superclass+
19
+ # Class or module this constant is an alias for
15
20
 
16
- def initialize(name, superclass = 'Object')
17
- @diagram = nil
18
- @full_name = nil
19
- @name = name
20
- @superclass = superclass
21
+ attr_accessor :is_alias_for
22
+
23
+ ##
24
+ # Return a RDoc::ClassModule of class +class_type+ that is a copy
25
+ # of module +module+. Used to promote modules to classes.
26
+
27
+ def self.from_module(class_type, mod)
28
+ klass = class_type.new(mod.name)
29
+ klass.comment = mod.comment
30
+ klass.parent = mod.parent
31
+ klass.section = mod.section
32
+ klass.viewer = mod.viewer
33
+
34
+ klass.attributes.concat mod.attributes
35
+ klass.method_list.concat mod.method_list
36
+ klass.aliases.concat mod.aliases
37
+ klass.external_aliases.concat mod.external_aliases
38
+ klass.constants.concat mod.constants
39
+ klass.includes.concat mod.includes
40
+
41
+ klass.methods_hash.update mod.methods_hash
42
+ klass.constants_hash.update mod.constants_hash
43
+
44
+ klass.current_section = mod.current_section
45
+ klass.in_files.concat mod.in_files
46
+ klass.sections.concat mod.sections
47
+ klass.unmatched_alias_lists = mod.unmatched_alias_lists
48
+ klass.current_section = mod.current_section
49
+ klass.visibility = mod.visibility
50
+
51
+ klass.classes_hash.update mod.classes_hash
52
+ klass.modules_hash.update mod.modules_hash
53
+ klass.metadata.update mod.metadata
54
+
55
+ klass.document_self = mod.received_nodoc ? nil : mod.document_self
56
+ klass.document_children = mod.document_children
57
+ klass.force_documentation = mod.force_documentation
58
+ klass.done_documenting = mod.done_documenting
59
+
60
+ # update the parent of all children
61
+
62
+ (klass.attributes +
63
+ klass.method_list +
64
+ klass.aliases +
65
+ klass.external_aliases +
66
+ klass.constants +
67
+ klass.includes +
68
+ klass.classes +
69
+ klass.modules).each do |obj|
70
+ obj.parent = klass
71
+ obj.full_name = nil
72
+ end
73
+
74
+ klass
75
+ end
76
+
77
+ ##
78
+ # Creates a new ClassModule with +name+ with optional +superclass+
79
+ #
80
+ # This is a constructor for subclasses, and must never be called directly.
81
+
82
+ def initialize(name, superclass = nil)
83
+ @constant_aliases = []
84
+ @diagram = nil
85
+ @is_alias_for = nil
86
+ @name = name
87
+ @superclass = superclass
21
88
  super()
22
89
  end
23
90
 
24
91
  ##
25
- # Ancestors list for this ClassModule (abstract)
92
+ # Ancestors list for this ClassModule: the list of included modules
93
+ # (classes will add their superclass if any).
94
+ #
95
+ # Returns the included classes or modules, not the includes
96
+ # themselves. The returned values are either String or
97
+ # RDoc::NormalModule instances (see RDoc::Include#module).
98
+ #
99
+ # The values are returned in reverse order of their inclusion,
100
+ # which is the order suitable for searching methods/attributes
101
+ # in the ancestors. The superclass, if any, comes last.
26
102
 
27
103
  def ancestors
28
- raise NotImplementedError
104
+ includes.map { |i| i.module }.reverse
105
+ end
106
+
107
+ ##
108
+ # Clears the comment. Used by the ruby parser.
109
+
110
+ def clear_comment
111
+ @comment = ''
29
112
  end
30
113
 
31
114
  ##
32
115
  # Appends +comment+ to the current comment, but separated by a rule. Works
33
116
  # more like <tt>+=</tt>.
34
117
 
35
- def comment=(comment)
118
+ def comment= comment
36
119
  return if comment.empty?
37
120
 
38
121
  comment = "#{@comment}\n---\n#{normalize_comment comment}" unless
@@ -41,10 +124,35 @@ class RDoc::ClassModule < RDoc::Context
41
124
  super
42
125
  end
43
126
 
127
+ ##
128
+ # Prepares this ClassModule for use by a generator.
129
+ #
130
+ # See RDoc::TopLevel::complete
131
+
132
+ def complete min_visibility
133
+ update_aliases
134
+ remove_nodoc_children
135
+ update_includes
136
+ remove_invisible min_visibility
137
+ end
138
+
139
+ ##
140
+ # Looks for a symbol in the #ancestors. See Context#find_local_symbol.
141
+
142
+ def find_ancestor_local_symbol symbol
143
+ ancestors.each do |m|
144
+ next if m.is_a?(String)
145
+ res = m.find_local_symbol(symbol)
146
+ return res if res
147
+ end
148
+
149
+ nil
150
+ end
151
+
44
152
  ##
45
153
  # Finds a class or module with +name+ in this namespace or its descendents
46
154
 
47
- def find_class_named(name)
155
+ def find_class_named name
48
156
  return self if full_name == name
49
157
  return self if @name == name
50
158
 
@@ -65,14 +173,8 @@ class RDoc::ClassModule < RDoc::Context
65
173
  end
66
174
  end
67
175
 
68
- ##
69
- # 'module' or 'class'
70
-
71
- def type
72
- module? ? 'module' : 'class'
73
- end
74
-
75
176
  def marshal_dump # :nodoc:
177
+ # TODO must store the singleton attribute
76
178
  attrs = attributes.sort.map do |attr|
77
179
  [attr.name, attr.rw]
78
180
  end
@@ -106,10 +208,13 @@ class RDoc::ClassModule < RDoc::Context
106
208
  end
107
209
 
108
210
  def marshal_load array # :nodoc:
211
+ # TODO must restore the singleton attribute
109
212
  initialize_methods_etc
110
213
  @document_self = true
111
214
  @done_documenting = false
112
215
  @current_section = nil
216
+ @parent = nil
217
+ @visibility = nil
113
218
 
114
219
  @name = array[1]
115
220
  @full_name = array[2]
@@ -183,6 +288,15 @@ class RDoc::ClassModule < RDoc::Context
183
288
  false
184
289
  end
185
290
 
291
+ ##
292
+ # Allows overriding the initial name.
293
+ #
294
+ # Used for modules and classes that are constant aliases.
295
+
296
+ def name= new_name
297
+ @name = new_name
298
+ end
299
+
186
300
  ##
187
301
  # Path to this class or module
188
302
 
@@ -190,12 +304,52 @@ class RDoc::ClassModule < RDoc::Context
190
304
  http_url RDoc::RDoc.current.generator.class_dir
191
305
  end
192
306
 
307
+ ##
308
+ # Name to use to generate the url:
309
+ # modules and classes that are aliases for another
310
+ # module or classe return the name of the latter.
311
+
312
+ def name_for_path
313
+ is_alias_for ? is_alias_for.full_name : full_name
314
+ end
315
+
316
+ ##
317
+ # Returns the classes and modules that are not constants
318
+ # aliasing another class or module. For use by formatters
319
+ # only (caches its result).
320
+
321
+ def non_aliases
322
+ @non_aliases ||= classes_and_modules.reject { |cm| cm.is_alias_for }
323
+ end
324
+
325
+ ##
326
+ # Updates the child modules or classes of class/module +parent+ by
327
+ # deleting the ones that have been removed from the documentation.
328
+ #
329
+ # +parent_hash+ is either <tt>parent.modules_hash</tt> or
330
+ # <tt>parent.classes_hash</tt> and +all_hash+ is ::all_modules_hash or
331
+ # ::all_classes_hash.
332
+
333
+ def remove_nodoc_children
334
+ prefix = self.full_name + '::'
335
+
336
+ modules_hash.each_key do |name|
337
+ full_name = prefix + name
338
+ modules_hash.delete name unless RDoc::TopLevel.all_modules_hash[full_name]
339
+ end
340
+
341
+ classes_hash.each_key do |name|
342
+ full_name = prefix + name
343
+ classes_hash.delete name unless RDoc::TopLevel.all_classes_hash[full_name]
344
+ end
345
+ end
346
+
193
347
  ##
194
348
  # Get the superclass of this class. Attempts to retrieve the superclass
195
349
  # object, returns the name if it is not known.
196
350
 
197
351
  def superclass
198
- RDoc::TopLevel.find_class_named_from(@superclass, parent) || @superclass
352
+ RDoc::TopLevel.find_class_named(@superclass) || @superclass
199
353
  end
200
354
 
201
355
  ##
@@ -203,12 +357,72 @@ class RDoc::ClassModule < RDoc::Context
203
357
 
204
358
  def superclass=(superclass)
205
359
  raise NoMethodError, "#{full_name} is a module" if module?
206
-
207
- @superclass = superclass if @superclass.nil? or @superclass == 'Object'
360
+ @superclass = superclass
208
361
  end
209
362
 
210
363
  def to_s # :nodoc:
211
- "#{self.class}: #{full_name} #{@comment} #{super}"
364
+ if is_alias_for then
365
+ "#{self.class.name} #{self.full_name} -> #{is_alias_for}"
366
+ else
367
+ super
368
+ end
369
+ end
370
+
371
+ ##
372
+ # 'module' or 'class'
373
+
374
+ def type
375
+ module? ? 'module' : 'class'
376
+ end
377
+
378
+ ##
379
+ # Updates the child modules & classes by replacing the ones that are
380
+ # aliases through a constant.
381
+ #
382
+ # The aliased module/class is replaced in the children and in
383
+ # RDoc::TopLevel::all_modules_hash or RDoc::TopLevel::all_classes_hash
384
+ # by a copy that has <tt>RDoc::ClassModule#is_alias_for</tt> set to
385
+ # the aliased module/class, and this copy is added to <tt>#aliases</tt>
386
+ # of the aliased module/class.
387
+ #
388
+ # Formatters can use the #non_aliases method to retrieve children that
389
+ # are not aliases, for instance to list the namespace content, since
390
+ # the aliased modules are included in the constants of the class/module,
391
+ # that are listed separately.
392
+
393
+ def update_aliases
394
+ constants.each do |const|
395
+ next unless cm = const.is_alias_for
396
+ cm_alias = cm.dup
397
+ cm_alias.name = const.name
398
+ cm_alias.parent = self
399
+ cm_alias.full_name = nil # force update for new parent
400
+ cm_alias.aliases.clear
401
+ cm_alias.is_alias_for = cm
402
+
403
+ if cm.module? then
404
+ RDoc::TopLevel.all_modules_hash[cm_alias.full_name] = cm_alias
405
+ modules_hash[const.name] = cm_alias
406
+ else
407
+ RDoc::TopLevel.all_classes_hash[cm_alias.full_name] = cm_alias
408
+ classes_hash[const.name] = cm_alias
409
+ end
410
+
411
+ cm.aliases << cm_alias
412
+ end
413
+ end
414
+
415
+ ##
416
+ # Deletes from #includes those whose module has been removed from the
417
+ # documentation.
418
+ #--
419
+ # FIXME: includes are not reliably removed, see _possible_bug test case
420
+
421
+ def update_includes
422
+ includes.reject! do |include|
423
+ mod = include.module
424
+ !(String === mod) && RDoc::TopLevel.all_modules_hash[mod.full_name].nil?
425
+ end
212
426
  end
213
427
 
214
428
  end
@@ -12,15 +12,16 @@ require 'rdoc/text'
12
12
  # * RDoc::Context
13
13
  # * RDoc::TopLevel
14
14
  # * RDoc::ClassModule
15
- # * RDoc::AnonClass
15
+ # * RDoc::AnonClass (never used so far)
16
16
  # * RDoc::NormalClass
17
17
  # * RDoc::NormalModule
18
18
  # * RDoc::SingleClass
19
- # * RDoc::AnyMethod
20
- # * RDoc::GhostMethod
21
- # * RDoc::MetaMethod
19
+ # * RDoc::MethodAttr
20
+ # * RDoc::Attr
21
+ # * RDoc::AnyMethod
22
+ # * RDoc::GhostMethod
23
+ # * RDoc::MetaMethod
22
24
  # * RDoc::Alias
23
- # * RDoc::Attr
24
25
  # * RDoc::Constant
25
26
  # * RDoc::Require
26
27
  # * RDoc::Include
@@ -47,12 +48,17 @@ class RDoc::CodeObject
47
48
  ##
48
49
  # Are we done documenting (ie, did we come across a :enddoc:)?
49
50
 
50
- attr_accessor :done_documenting
51
+ attr_reader :done_documenting
52
+
53
+ ##
54
+ # Which file this code object was defined in
55
+
56
+ attr_reader :file
51
57
 
52
58
  ##
53
59
  # Force documentation of this CodeObject
54
60
 
55
- attr_accessor :force_documentation
61
+ attr_reader :force_documentation
56
62
 
57
63
  ##
58
64
  # Hash of arbitrary metadata for this CodeObject
@@ -64,6 +70,11 @@ class RDoc::CodeObject
64
70
 
65
71
  attr_accessor :parent
66
72
 
73
+ ##
74
+ # Did we ever receive a +:nodoc:+ directive?
75
+
76
+ attr_reader :received_nodoc
77
+
67
78
  ##
68
79
  # Which section are we in
69
80
 
@@ -80,15 +91,17 @@ class RDoc::CodeObject
80
91
  # Creates a new CodeObject that will document itself and its children
81
92
 
82
93
  def initialize
83
- @metadata = {}
84
- @comment = ''
94
+ @metadata = {}
95
+ @comment = ''
96
+ @parent = nil
97
+ @file = nil
98
+ @full_name = nil
85
99
 
86
100
  @document_children = true
87
101
  @document_self = true
88
102
  @done_documenting = false
89
103
  @force_documentation = false
90
-
91
- @parent = nil
104
+ @received_nodoc = false
92
105
  end
93
106
 
94
107
  ##
@@ -108,28 +121,64 @@ class RDoc::CodeObject
108
121
  end
109
122
 
110
123
  ##
111
- # Enables or disables documentation of this CodeObject's children. Calls
112
- # remove_classes_and_modules when disabling.
124
+ # Enables or disables documentation of this CodeObject's children unless it
125
+ # has been turned off by :enddoc:
113
126
 
114
127
  def document_children=(document_children)
115
- @document_children = document_children
116
- remove_classes_and_modules unless document_children
128
+ @document_children = document_children unless @done_documenting
117
129
  end
118
130
 
119
131
  ##
120
- # Enables or disables documentation of this CodeObject. Calls
121
- # remove_methods_etc when disabling.
132
+ # Enables or disables documentation of this CodeObject unless it has been
133
+ # turned off by :enddoc:. If the argument is +nil+ it means the
134
+ # documentation is turned off by +:nodoc:+.
122
135
 
123
136
  def document_self=(document_self)
137
+ return if @done_documenting
138
+
124
139
  @document_self = document_self
125
- remove_methods_etc unless document_self
140
+ @received_nodoc = true if document_self.nil?
126
141
  end
127
142
 
128
143
  ##
129
- # Does this class have a comment with content or is document_self false.
144
+ # Does this object have a comment with content or is #received_nodoc true?
130
145
 
131
146
  def documented?
132
- !(@document_self and @comment.empty?)
147
+ @received_nodoc or !@comment.empty?
148
+ end
149
+
150
+ ##
151
+ # Turns documentation on/off, and turns on/off #document_self
152
+ # and #document_children.
153
+ #
154
+ # Once documentation has been turned off (by +:enddoc:+),
155
+ # the object will refuse to turn #document_self or
156
+ # #document_children on, so +:doc:+ and +:start_doc:+ directives
157
+ # will have no effect in the current file.
158
+
159
+ def done_documenting=(value)
160
+ @done_documenting = value
161
+ @document_self = !value
162
+ @document_children = @document_self
163
+ end
164
+
165
+ ##
166
+ # Force the documentation of this object unless documentation
167
+ # has been turned off by :endoc:
168
+ #--
169
+ # HACK untested, was assigning to an ivar
170
+
171
+ def force_documentation=(value)
172
+ @force_documentation = value unless @done_documenting
173
+ end
174
+
175
+ ##
176
+ # Sets the full_name overriding any computed full name.
177
+ #
178
+ # Set to +nil+ to clear RDoc's cached value
179
+
180
+ def full_name= full_name
181
+ @full_name = full_name
133
182
  end
134
183
 
135
184
  ##
@@ -147,23 +196,19 @@ class RDoc::CodeObject
147
196
  end
148
197
 
149
198
  ##
150
- # Callback called upon disabling documentation of children. See
151
- # #document_children=
152
-
153
- def remove_classes_and_modules
154
- end
155
-
156
- ##
157
- # Callback called upon disabling documentation of ourself. See
158
- # #document_self=
199
+ # Records the RDoc::TopLevel (file) where this code object was defined
159
200
 
160
- def remove_methods_etc
201
+ def record_location top_level
202
+ @file = top_level
161
203
  end
162
204
 
163
205
  ##
164
- # Enable capture of documentation
206
+ # Enable capture of documentation unless documentation has been
207
+ # turned off by :endoc:
165
208
 
166
209
  def start_doc
210
+ return if @done_documenting
211
+
167
212
  @document_self = true
168
213
  @document_children = true
169
214
  end