rdoc 4.0.1 → 4.1.0.preview.3

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 (140) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/.autotest +1 -3
  5. data/{DEVELOPERS.rdoc → CONTRIBUTING.rdoc} +28 -3
  6. data/ExampleMarkdown.md +37 -0
  7. data/ExampleRDoc.rdoc +208 -0
  8. data/History.rdoc +81 -0
  9. data/Manifest.txt +11 -2
  10. data/README.rdoc +5 -5
  11. data/Rakefile +34 -4
  12. data/lib/rdoc.rb +4 -3
  13. data/lib/rdoc/any_method.rb +48 -4
  14. data/lib/rdoc/class_module.rb +16 -2
  15. data/lib/rdoc/code_object.rb +85 -24
  16. data/lib/rdoc/comment.rb +0 -3
  17. data/lib/rdoc/constant.rb +9 -1
  18. data/lib/rdoc/context.rb +20 -2
  19. data/lib/rdoc/cross_reference.rb +1 -1
  20. data/lib/rdoc/extend.rb +4 -112
  21. data/lib/rdoc/generator/darkfish.rb +46 -7
  22. data/lib/rdoc/generator/template/darkfish/_footer.rhtml +4 -4
  23. data/lib/rdoc/generator/template/darkfish/_head.rhtml +14 -8
  24. data/lib/rdoc/generator/template/darkfish/_sidebar_VCS_info.rhtml +4 -3
  25. data/lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml +3 -3
  26. data/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml +3 -4
  27. data/lib/rdoc/generator/template/darkfish/_sidebar_in_files.rhtml +4 -3
  28. data/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml +3 -4
  29. data/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml +3 -3
  30. data/lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml +4 -4
  31. data/lib/rdoc/generator/template/darkfish/_sidebar_navigation.rhtml +9 -5
  32. data/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml +5 -5
  33. data/lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml +4 -3
  34. data/lib/rdoc/generator/template/darkfish/_sidebar_search.rhtml +12 -7
  35. data/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml +5 -4
  36. data/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml +6 -7
  37. data/lib/rdoc/generator/template/darkfish/class.rhtml +36 -41
  38. data/lib/rdoc/generator/template/darkfish/fonts.css +167 -0
  39. data/lib/rdoc/generator/template/darkfish/fonts/Lato-Light.ttf +0 -0
  40. data/lib/rdoc/generator/template/darkfish/fonts/Lato-LightItalic.ttf +0 -0
  41. data/lib/rdoc/generator/template/darkfish/fonts/Lato-Regular.ttf +0 -0
  42. data/lib/rdoc/generator/template/darkfish/fonts/Lato-RegularItalic.ttf +0 -0
  43. data/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttf +0 -0
  44. data/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttf +0 -0
  45. data/lib/rdoc/generator/template/darkfish/images/add.png +0 -0
  46. data/lib/rdoc/generator/template/darkfish/images/arrow_up.png +0 -0
  47. data/lib/rdoc/generator/template/darkfish/images/delete.png +0 -0
  48. data/lib/rdoc/generator/template/darkfish/images/tag_blue.png +0 -0
  49. data/lib/rdoc/generator/template/darkfish/index.rhtml +11 -7
  50. data/lib/rdoc/generator/template/darkfish/js/darkfish.js +0 -15
  51. data/lib/rdoc/generator/template/darkfish/js/search.js +12 -4
  52. data/lib/rdoc/generator/template/darkfish/page.rhtml +9 -9
  53. data/lib/rdoc/generator/template/darkfish/rdoc.css +226 -241
  54. data/lib/rdoc/generator/template/darkfish/servlet_not_found.rhtml +5 -5
  55. data/lib/rdoc/generator/template/darkfish/servlet_root.rhtml +13 -6
  56. data/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml +17 -14
  57. data/lib/rdoc/include.rb +4 -114
  58. data/lib/rdoc/known_classes.rb +1 -0
  59. data/lib/rdoc/markdown.kpeg +126 -117
  60. data/lib/rdoc/markdown.rb +404 -389
  61. data/lib/rdoc/markdown/literals_1_8.kpeg +1 -1
  62. data/lib/rdoc/markdown/literals_1_8.rb +15 -12
  63. data/lib/rdoc/markdown/literals_1_9.kpeg +1 -1
  64. data/lib/rdoc/markdown/literals_1_9.rb +15 -12
  65. data/lib/rdoc/markup.rb +10 -13
  66. data/lib/rdoc/markup/attribute_manager.rb +3 -2
  67. data/lib/rdoc/markup/formatter.rb +3 -3
  68. data/lib/rdoc/markup/heading.rb +13 -0
  69. data/lib/rdoc/markup/parser.rb +10 -3
  70. data/lib/rdoc/markup/pre_process.rb +1 -1
  71. data/lib/rdoc/markup/to_html.rb +46 -31
  72. data/lib/rdoc/markup/to_html_crossref.rb +3 -0
  73. data/lib/rdoc/markup/to_joined_paragraph.rb +1 -1
  74. data/lib/rdoc/markup/to_markdown.rb +7 -5
  75. data/lib/rdoc/markup/verbatim.rb +1 -1
  76. data/lib/rdoc/method_attr.rb +13 -1
  77. data/lib/rdoc/mixin.rb +120 -0
  78. data/lib/rdoc/normal_class.rb +4 -0
  79. data/lib/rdoc/normal_module.rb +4 -0
  80. data/lib/rdoc/options.rb +42 -8
  81. data/lib/rdoc/parser.rb +4 -2
  82. data/lib/rdoc/parser/c.rb +13 -7
  83. data/lib/rdoc/parser/ruby.rb +683 -480
  84. data/lib/rdoc/rdoc.rb +4 -3
  85. data/lib/rdoc/ri/driver.rb +174 -103
  86. data/lib/rdoc/ri/paths.rb +6 -6
  87. data/lib/rdoc/ruby_lex.rb +125 -102
  88. data/lib/rdoc/ruby_token.rb +41 -40
  89. data/lib/rdoc/servlet.rb +16 -6
  90. data/lib/rdoc/stats.rb +61 -48
  91. data/lib/rdoc/store.rb +5 -3
  92. data/lib/rdoc/test_case.rb +39 -0
  93. data/lib/rdoc/tom_doc.rb +28 -4
  94. data/lib/rdoc/top_level.rb +2 -2
  95. data/test/test_rdoc_any_method.rb +104 -1
  96. data/test/test_rdoc_class_module.rb +9 -15
  97. data/test/test_rdoc_code_object.rb +133 -8
  98. data/test/test_rdoc_context.rb +17 -0
  99. data/test/test_rdoc_context_section.rb +0 -7
  100. data/test/test_rdoc_cross_reference.rb +4 -3
  101. data/test/test_rdoc_generator_darkfish.rb +61 -19
  102. data/test/test_rdoc_generator_json_index.rb +0 -11
  103. data/test/test_rdoc_generator_ri.rb +0 -8
  104. data/test/test_rdoc_markdown.rb +15 -12
  105. data/test/test_rdoc_markdown_test.rb +0 -7
  106. data/test/test_rdoc_markup_attribute_manager.rb +121 -0
  107. data/test/test_rdoc_markup_document.rb +0 -7
  108. data/test/test_rdoc_markup_formatter.rb +29 -3
  109. data/test/test_rdoc_markup_heading.rb +9 -0
  110. data/test/test_rdoc_markup_parser.rb +0 -7
  111. data/test/test_rdoc_markup_pre_process.rb +15 -3
  112. data/test/test_rdoc_markup_raw.rb +0 -7
  113. data/test/test_rdoc_markup_to_html.rb +50 -8
  114. data/test/test_rdoc_markup_to_html_crossref.rb +7 -0
  115. data/test/test_rdoc_markup_to_html_snippet.rb +4 -4
  116. data/test/test_rdoc_markup_to_markdown.rb +6 -0
  117. data/test/test_rdoc_method_attr.rb +8 -0
  118. data/test/test_rdoc_normal_class.rb +5 -0
  119. data/test/test_rdoc_normal_module.rb +5 -0
  120. data/test/test_rdoc_options.rb +61 -22
  121. data/test/test_rdoc_parser.rb +10 -0
  122. data/test/test_rdoc_parser_c.rb +17 -5
  123. data/test/test_rdoc_parser_changelog.rb +0 -7
  124. data/test/test_rdoc_parser_rd.rb +0 -7
  125. data/test/test_rdoc_parser_ruby.rb +305 -28
  126. data/test/test_rdoc_rd_block_parser.rb +0 -8
  127. data/test/test_rdoc_rd_inline_parser.rb +0 -1
  128. data/test/test_rdoc_rdoc.rb +27 -1
  129. data/test/test_rdoc_ri_driver.rb +19 -7
  130. data/test/test_rdoc_ruby_lex.rb +116 -9
  131. data/test/test_rdoc_rubygems_hook.rb +1 -1
  132. data/test/test_rdoc_servlet.rb +44 -6
  133. data/test/test_rdoc_stats.rb +161 -141
  134. data/test/test_rdoc_store.rb +11 -19
  135. data/test/test_rdoc_text.rb +0 -7
  136. data/test/test_rdoc_tom_doc.rb +44 -16
  137. data/test/xref_test_case.rb +2 -0
  138. metadata +28 -27
  139. metadata.gz.sig +0 -0
  140. data/test/test_attribute_manager.rb +0 -120
@@ -145,6 +145,9 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
145
145
 
146
146
  if path =~ /#/ then
147
147
  path << "-label-#{label}"
148
+ elsif ref.sections and
149
+ ref.sections.any? { |section| label == section.title } then
150
+ path << "##{label}"
148
151
  else
149
152
  path << "#label-#{label}"
150
153
  end if label
@@ -47,7 +47,7 @@ class RDoc::Markup::ToJoinedParagraph < RDoc::Markup::Formatter
47
47
  end
48
48
  end
49
49
 
50
- # TODO use Enumerable#chunk when ruby 1.8 support is dropped
50
+ # TODO use Enumerable#chunk when Ruby 1.8 support is dropped
51
51
  #parts = paragraph.parts.chunk do |part|
52
52
  # String === part
53
53
  #end.map do |string, chunk|
@@ -147,15 +147,17 @@ class RDoc::Markup::ToMarkdown < RDoc::Markup::ToRdoc
147
147
 
148
148
  def handle_rdoc_link url
149
149
  case url
150
- when /\Ardoc-ref:/ then
150
+ when /^rdoc-ref:/ then
151
151
  $'
152
- when /\Ardoc-label:footmark-(\d+)/ then
152
+ when /^rdoc-label:footmark-(\d+)/ then
153
153
  "[^#{$1}]:"
154
- when /\Ardoc-label:foottext-(\d+)/ then
154
+ when /^rdoc-label:foottext-(\d+)/ then
155
155
  "[^#{$1}]"
156
- when /\Ardoc-label:label-/ then
156
+ when /^rdoc-label:label-/ then
157
157
  gen_url url, $'
158
- when /\Ardoc-[a-z]+:/ then
158
+ when /^rdoc-image:/ then
159
+ "![](#{$'})"
160
+ when /^rdoc-[a-z]+:/ then
159
161
  $'
160
162
  end
161
163
  end
@@ -65,7 +65,7 @@ class RDoc::Markup::Verbatim < RDoc::Markup::Raw
65
65
  end
66
66
 
67
67
  ##
68
- # Is this verbatim section ruby code?
68
+ # Is this verbatim section Ruby code?
69
69
 
70
70
  def ruby?
71
71
  @format ||= nil # TODO for older ri data, switch the tree to marshal_dump
@@ -94,6 +94,18 @@ class RDoc::MethodAttr < RDoc::CodeObject
94
94
  @params = nil
95
95
  end
96
96
 
97
+ ##
98
+ # Resets cached data for the object so it can be rebuilt by accessor methods
99
+
100
+ def initialize_copy other # :nodoc:
101
+ @full_name = nil
102
+ end
103
+
104
+ def initialize_visibility # :nodoc:
105
+ super
106
+ @see = nil
107
+ end
108
+
97
109
  ##
98
110
  # Order by #singleton then #name
99
111
 
@@ -211,7 +223,7 @@ class RDoc::MethodAttr < RDoc::CodeObject
211
223
  end
212
224
 
213
225
  ##
214
- # Attempts to sanitize the content passed by the ruby parser:
226
+ # Attempts to sanitize the content passed by the Ruby parser:
215
227
  # remove outer parentheses, etc.
216
228
 
217
229
  def block_params=(value)
@@ -0,0 +1,120 @@
1
+ ##
2
+ # A Mixin adds features from a module into another context. RDoc::Include and
3
+ # RDoc::Extend are both mixins.
4
+
5
+ class RDoc::Mixin < RDoc::CodeObject
6
+
7
+ ##
8
+ # Name of included module
9
+
10
+ attr_accessor :name
11
+
12
+ ##
13
+ # Creates a new Mixin for +name+ with +comment+
14
+
15
+ def initialize(name, comment)
16
+ super()
17
+ @name = name
18
+ self.comment = comment
19
+ @module = nil # cache for module if found
20
+ end
21
+
22
+ ##
23
+ # Mixins are sorted by name
24
+
25
+ def <=> other
26
+ return unless self.class === other
27
+
28
+ name <=> other.name
29
+ end
30
+
31
+ def == other # :nodoc:
32
+ self.class === other and @name == other.name
33
+ end
34
+
35
+ alias eql? == # :nodoc:
36
+
37
+ ##
38
+ # Full name based on #module
39
+
40
+ def full_name
41
+ m = self.module
42
+ RDoc::ClassModule === m ? m.full_name : @name
43
+ end
44
+
45
+ def hash # :nodoc:
46
+ [@name, self.module].hash
47
+ end
48
+
49
+ def inspect # :nodoc:
50
+ "#<%s:0x%x %s.%s %s>" % [
51
+ self.class,
52
+ object_id,
53
+ parent_name, self.class.name.downcase, @name,
54
+ ]
55
+ end
56
+
57
+ ##
58
+ # Attempts to locate the included module object. Returns the name if not
59
+ # known.
60
+ #
61
+ # The scoping rules of Ruby to resolve the name of an included module are:
62
+ # - first look into the children of the current context;
63
+ # - if not found, look into the children of included modules,
64
+ # in reverse inclusion order;
65
+ # - if still not found, go up the hierarchy of names.
66
+ #
67
+ # This method has <code>O(n!)</code> behavior when the module calling
68
+ # include is referencing nonexistent modules. Avoid calling #module until
69
+ # after all the files are parsed. This behavior is due to ruby's constant
70
+ # lookup behavior.
71
+ #
72
+ # As of the beginning of October, 2011, no gem includes nonexistent modules.
73
+
74
+ def module
75
+ return @module if @module
76
+
77
+ # search the current context
78
+ return @name unless parent
79
+ full_name = parent.child_name(@name)
80
+ @module = @store.modules_hash[full_name]
81
+ return @module if @module
82
+ return @name if @name =~ /^::/
83
+
84
+ # search the includes before this one, in reverse order
85
+ searched = parent.includes.take_while { |i| i != self }.reverse
86
+ searched.each do |i|
87
+ inc = i.module
88
+ next if String === inc
89
+ full_name = inc.child_name(@name)
90
+ @module = @store.modules_hash[full_name]
91
+ return @module if @module
92
+ end
93
+
94
+ # go up the hierarchy of names
95
+ up = parent.parent
96
+ while up
97
+ full_name = up.child_name(@name)
98
+ @module = @store.modules_hash[full_name]
99
+ return @module if @module
100
+ up = up.parent
101
+ end
102
+
103
+ @name
104
+ end
105
+
106
+ ##
107
+ # Sets the store for this class or module and its contained code objects.
108
+
109
+ def store= store
110
+ super
111
+
112
+ @file = @store.add_file @file.full_name if @file
113
+ end
114
+
115
+ def to_s # :nodoc:
116
+ "#{self.class.name.downcase} #@name in: #{parent}"
117
+ end
118
+
119
+ end
120
+
@@ -20,6 +20,10 @@ class RDoc::NormalClass < RDoc::ClassModule
20
20
  end
21
21
  end
22
22
 
23
+ def aref_prefix # :nodoc:
24
+ 'class'
25
+ end
26
+
23
27
  ##
24
28
  # The definition of this class, <tt>class MyClassName</tt>
25
29
 
@@ -3,6 +3,10 @@
3
3
 
4
4
  class RDoc::NormalModule < RDoc::ClassModule
5
5
 
6
+ def aref_prefix # :nodoc:
7
+ 'module'
8
+ end
9
+
6
10
  def inspect # :nodoc:
7
11
  "#<%s:0x%x module %s includes: %p extends: %p attributes: %p methods: %p aliases: %p>" % [
8
12
  self.class, object_id,
@@ -240,6 +240,10 @@ class RDoc::Options
240
240
 
241
241
  attr_accessor :option_parser
242
242
 
243
+ ##
244
+ # Output heading decorations?
245
+ attr_accessor :output_decoration
246
+
243
247
  ##
244
248
  # Directory where guides, FAQ, and other pages not associated with a class
245
249
  # live. You may leave this unset if these are at the root of your project.
@@ -288,6 +292,11 @@ class RDoc::Options
288
292
 
289
293
  attr_accessor :template_dir
290
294
 
295
+ ##
296
+ # Additional template stylesheets
297
+
298
+ attr_accessor :template_stylesheets
299
+
291
300
  ##
292
301
  # Documentation title
293
302
 
@@ -309,9 +318,12 @@ class RDoc::Options
309
318
  attr_accessor :webcvs
310
319
 
311
320
  ##
312
- # Minimum visibility of a documented method. One of +:public+,
313
- # +:protected+, +:private+. May be overridden on a per-method
314
- # basis with the :doc: directive.
321
+ # Minimum visibility of a documented method. One of +:public+, +:protected+,
322
+ # +:private+ or +:nodoc+.
323
+ #
324
+ # The +:nodoc+ visibility ignores all directives related to visibility. The
325
+ # other visibilities may be overridden on a per-method basis with the :doc:
326
+ # directive.
315
327
 
316
328
  attr_accessor :visibility
317
329
 
@@ -337,6 +349,7 @@ class RDoc::Options
337
349
  @op_dir = nil
338
350
  @page_dir = nil
339
351
  @pipe = false
352
+ @output_decoration = true
340
353
  @rdoc_include = []
341
354
  @root = Pathname(Dir.pwd)
342
355
  @show_hash = false
@@ -345,6 +358,7 @@ class RDoc::Options
345
358
  @tab_width = 8
346
359
  @template = nil
347
360
  @template_dir = nil
361
+ @template_stylesheets = []
348
362
  @title = nil
349
363
  @update_output_dir = true
350
364
  @verbosity = 1
@@ -478,6 +492,8 @@ class RDoc::Options
478
492
  @op_dir ||= 'doc'
479
493
 
480
494
  @rdoc_include << "." if @rdoc_include.empty?
495
+ root = @root.to_s
496
+ @rdoc_include << root unless @rdoc_include.include?(root)
481
497
 
482
498
  if @exclude.nil? or Regexp === @exclude then
483
499
  # done, #finish is being re-run
@@ -593,6 +609,7 @@ Usage: #{opt.program_name} [options] [names...]
593
609
  parsers.sort.each do |parser, regexp|
594
610
  opt.banner << " - #{parser}: #{regexp.join ', '}\n"
595
611
  end
612
+ opt.banner << " - TomDoc: Only in ruby files\n"
596
613
 
597
614
  opt.banner << "\n The following options are deprecated:\n\n"
598
615
 
@@ -707,17 +724,19 @@ Usage: #{opt.program_name} [options] [names...]
707
724
 
708
725
  opt.separator nil
709
726
 
710
- opt.on("--tab-width=WIDTH", "-w", OptionParser::DecimalInteger,
727
+ opt.on("--tab-width=WIDTH", "-w", Integer,
711
728
  "Set the width of tab characters.") do |value|
729
+ raise OptionParser::InvalidArgument,
730
+ "#{value} is an invalid tab width" if value <= 0
712
731
  @tab_width = value
713
732
  end
714
733
 
715
734
  opt.separator nil
716
735
 
717
- opt.on("--visibility=VISIBILITY", "-V", RDoc::VISIBILITIES,
736
+ opt.on("--visibility=VISIBILITY", "-V", RDoc::VISIBILITIES + [:nodoc],
718
737
  "Minimum visibility to document a method.",
719
- "One of 'public', 'protected' (the default)",
720
- "or 'private'. Can be abbreviated.") do |value|
738
+ "One of 'public', 'protected' (the default),",
739
+ "'private' or 'nodoc' (show everything)") do |value|
721
740
  @visibility = value
722
741
  end
723
742
 
@@ -873,6 +892,14 @@ Usage: #{opt.program_name} [options] [names...]
873
892
 
874
893
  opt.separator nil
875
894
 
895
+ opt.on("--template-stylesheets=FILES", PathArray,
896
+ "Set (or add to) the list of files to",
897
+ "include with the html template.") do |value|
898
+ @template_stylesheets << value
899
+ end
900
+
901
+ opt.separator nil
902
+
876
903
  opt.on("--title=TITLE", "-t",
877
904
  "Set TITLE as the title for HTML output.") do |value|
878
905
  @title = value
@@ -975,13 +1002,20 @@ Usage: #{opt.program_name} [options] [names...]
975
1002
 
976
1003
  opt.separator nil
977
1004
 
978
- opt.on("--verbose", "-v",
1005
+ opt.on("--verbose", "-V",
979
1006
  "Display extra progress as RDoc parses") do |value|
980
1007
  @verbosity = 2
981
1008
  end
982
1009
 
983
1010
  opt.separator nil
984
1011
 
1012
+ opt.on("--version", "-v", "print the version") do
1013
+ puts opt.version
1014
+ exit
1015
+ end
1016
+
1017
+ opt.separator nil
1018
+
985
1019
  opt.on("--help",
986
1020
  "Display this help") do
987
1021
  RDoc::RDoc::GENERATORS.each_key do |generator|
@@ -268,9 +268,11 @@ class RDoc::Parser
268
268
 
269
269
  markup = Regexp.escape markup
270
270
 
271
- RDoc::Parser.parsers.find do |_, parser|
271
+ _, selected = RDoc::Parser.parsers.find do |_, parser|
272
272
  /^#{markup}$/i =~ parser.name.sub(/.*:/, '')
273
- end.last
273
+ end
274
+
275
+ selected
274
276
  end
275
277
 
276
278
  ##
@@ -123,7 +123,7 @@ class RDoc::Parser::C < RDoc::Parser
123
123
  include RDoc::Text
124
124
 
125
125
  ##
126
- # Maps C variable names to names of ruby classes or modules
126
+ # Maps C variable names to names of Ruby classes or modules
127
127
 
128
128
  attr_reader :classes
129
129
 
@@ -139,7 +139,7 @@ class RDoc::Parser::C < RDoc::Parser
139
139
  attr_reader :enclosure_dependencies
140
140
 
141
141
  ##
142
- # Maps C variable names to names of ruby classes (and singleton classes)
142
+ # Maps C variable names to names of Ruby classes (and singleton classes)
143
143
 
144
144
  attr_reader :known_classes
145
145
 
@@ -150,7 +150,7 @@ class RDoc::Parser::C < RDoc::Parser
150
150
  attr_reader :missing_dependencies
151
151
 
152
152
  ##
153
- # Maps C variable names to names of ruby singleton classes
153
+ # Maps C variable names to names of Ruby singleton classes
154
154
 
155
155
  attr_reader :singleton_classes
156
156
 
@@ -228,17 +228,23 @@ class RDoc::Parser::C < RDoc::Parser
228
228
  end
229
229
  end
230
230
 
231
- def deduplicate_method_name class_obj, method_name
231
+ ##
232
+ # If two ruby methods share a C implementation (and comment) this
233
+ # deduplicates the examples in the call_seq for the method to reduce
234
+ # confusion in the output.
235
+
236
+ def deduplicate_method_name class_obj, method_name # :nodoc:
232
237
  return unless
233
238
  method = class_obj.method_list.find { |m| m.name == method_name }
234
239
  return unless call_seq = method.call_seq
235
240
 
236
- method_name = method_name[0, 1] unless method_name =~ /\A\w/
241
+ method_name = method_name[0, 1] if method_name =~ /\A\[/
237
242
 
238
- entries = call_seq.split "\n"
243
+ entries = call_seq.split "\n"
239
244
 
240
245
  matching = entries.select do |entry|
241
- entry =~ /^\w*\.?#{Regexp.escape method_name}/
246
+ entry =~ /^\w*\.?#{Regexp.escape method_name}/ or
247
+ entry =~ /\s#{Regexp.escape method_name}\s/
242
248
  end
243
249
 
244
250
  method.call_seq = matching.join "\n"
@@ -107,6 +107,9 @@ $TOKEN_DEBUG ||= nil
107
107
  # ##
108
108
  # # :singleton-method: some_method!
109
109
  #
110
+ # You can define arguments for metaprogrammed methods via either the
111
+ # :call-seq:, :arg: or :args: directives.
112
+ #
110
113
  # Additionally you can mark a method as an attribute by
111
114
  # using :attr:, :attr_reader:, :attr_writer: or :attr_accessor:. Just like
112
115
  # for :method:, the name is optional.
@@ -165,6 +168,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
165
168
  @scanner.exception_on_syntax_error = false
166
169
  @prev_seek = nil
167
170
  @markup = @options.markup
171
+ @track_visibility = :nodoc != @options.visibility
168
172
 
169
173
  @encoding = nil
170
174
  @encoding = @options.encoding if Object.const_defined? :Encoding
@@ -172,6 +176,48 @@ class RDoc::Parser::Ruby < RDoc::Parser
172
176
  reset
173
177
  end
174
178
 
179
+ ##
180
+ # Retrieves the read token stream and replaces +pattern+ with +replacement+
181
+ # using gsub. If the result is only a ";" returns an empty string.
182
+
183
+ def get_tkread_clean pattern, replacement # :nodoc:
184
+ read = get_tkread.gsub(pattern, replacement).strip
185
+ return '' if read == ';'
186
+ read
187
+ end
188
+
189
+ ##
190
+ # Extracts the visibility information for the visibility token +tk+.
191
+ #
192
+ # Returns the visibility type (a string), the visibility (a symbol) and
193
+ # +singleton+ if the methods following should be converted to singleton
194
+ # methods.
195
+
196
+ def get_visibility_information tk # :nodoc:
197
+ vis_type = tk.name
198
+ singleton = false
199
+
200
+ vis =
201
+ case vis_type
202
+ when 'private' then :private
203
+ when 'protected' then :protected
204
+ when 'public' then :public
205
+ when 'private_class_method' then
206
+ singleton = true
207
+ :private
208
+ when 'public_class_method' then
209
+ singleton = true
210
+ :public
211
+ when 'module_function' then
212
+ singleton = true
213
+ :public
214
+ else
215
+ raise RDoc::Error, "Invalid visibility: #{tk.name}"
216
+ end
217
+
218
+ return vis_type, vis, singleton
219
+ end
220
+
175
221
  ##
176
222
  # Look for the first comment in a file that isn't a shebang line.
177
223
 
@@ -208,6 +254,41 @@ class RDoc::Parser::Ruby < RDoc::Parser
208
254
  new_comment comment
209
255
  end
210
256
 
257
+ ##
258
+ # Consumes trailing whitespace from the token stream
259
+
260
+ def consume_trailing_spaces # :nodoc:
261
+ get_tkread
262
+ skip_tkspace false
263
+ end
264
+
265
+ ##
266
+ # Creates a new attribute in +container+ with +name+.
267
+
268
+ def create_attr container, single, name, rw, comment # :nodoc:
269
+ att = RDoc::Attr.new get_tkread, name, rw, comment, single == SINGLE
270
+ record_location att
271
+
272
+ container.add_attribute att
273
+ @stats.add_attribute att
274
+
275
+ att
276
+ end
277
+
278
+ ##
279
+ # Creates a module alias in +container+ at +rhs_name+ (or at the top-level
280
+ # for "::") with the name from +constant+.
281
+
282
+ def create_module_alias container, constant, rhs_name # :nodoc:
283
+ mod = if rhs_name =~ /^::/ then
284
+ @store.find_class_or_module rhs_name
285
+ else
286
+ container.find_module_named rhs_name
287
+ end
288
+
289
+ container.add_module_alias mod, constant.name, @top_level if mod
290
+ end
291
+
211
292
  ##
212
293
  # Aborts with +msg+
213
294
 
@@ -265,10 +346,11 @@ class RDoc::Parser::Ruby < RDoc::Parser
265
346
  else
266
347
  c = prev_container.add_module RDoc::NormalModule, name_t.name
267
348
  c.ignore unless prev_container.document_children
349
+ @top_level.add_to_classes_or_modules c
268
350
  c
269
351
  end
270
352
 
271
- container.record_location @top_level
353
+ record_location container
272
354
 
273
355
  get_tk
274
356
  skip_tkspace false
@@ -285,17 +367,13 @@ class RDoc::Parser::Ruby < RDoc::Parser
285
367
  # Return a superclass, which can be either a constant of an expression
286
368
 
287
369
  def get_class_specification
288
- tk = get_tk
289
- return 'self' if TkSELF === tk
290
- return '' if TkGVAR === tk
291
-
292
- res = ''
293
- while TkCOLON2 === tk or TkCOLON3 === tk or TkCONSTANT === tk do
294
- res += tk.name
295
- tk = get_tk
370
+ case peek_tk
371
+ when TkSELF then return 'self'
372
+ when TkGVAR then return ''
296
373
  end
297
374
 
298
- unget_tk(tk)
375
+ res = get_constant
376
+
299
377
  skip_tkspace false
300
378
 
301
379
  get_tkread # empty out read buffer
@@ -326,9 +404,6 @@ class RDoc::Parser::Ruby < RDoc::Parser
326
404
  tk = get_tk
327
405
  end
328
406
 
329
- # if res.empty?
330
- # warn("Unexpected token #{tk} in constant")
331
- # end
332
407
  unget_tk(tk)
333
408
  res
334
409
  end
@@ -358,6 +433,68 @@ class RDoc::Parser::Ruby < RDoc::Parser
358
433
  name
359
434
  end
360
435
 
436
+ ##
437
+ # Little hack going on here. In the statement:
438
+ #
439
+ # f = 2*(1+yield)
440
+ #
441
+ # We see the RPAREN as the next token, so we need to exit early. This still
442
+ # won't catch all cases (such as "a = yield + 1"
443
+
444
+ def get_end_token tk # :nodoc:
445
+ case tk
446
+ when TkLPAREN, TkfLPAREN
447
+ TkRPAREN
448
+ when TkRPAREN
449
+ nil
450
+ else
451
+ TkNL
452
+ end
453
+ end
454
+
455
+ ##
456
+ # Retrieves the method container for a singleton method.
457
+
458
+ def get_method_container container, name_t # :nodoc:
459
+ prev_container = container
460
+ container = container.find_module_named(name_t.name)
461
+
462
+ unless container then
463
+ constant = prev_container.constants.find do |const|
464
+ const.name == name_t.name
465
+ end
466
+
467
+ if constant then
468
+ parse_method_dummy prev_container
469
+ return
470
+ end
471
+ end
472
+
473
+ unless container then
474
+ # TODO seems broken, should starting at Object in @store
475
+ obj = name_t.name.split("::").inject(Object) do |state, item|
476
+ state.const_get(item)
477
+ end rescue nil
478
+
479
+ type = obj.class == Class ? RDoc::NormalClass : RDoc::NormalModule
480
+
481
+ unless [Class, Module].include?(obj.class) then
482
+ warn("Couldn't find #{name_t.name}. Assuming it's a module")
483
+ end
484
+
485
+ if type == RDoc::NormalClass then
486
+ sclass = obj.superclass ? obj.superclass.name : nil
487
+ container = prev_container.add_class type, name_t.name, sclass
488
+ else
489
+ container = prev_container.add_module type, name_t.name
490
+ end
491
+
492
+ record_location container
493
+ end
494
+
495
+ container
496
+ end
497
+
361
498
  ##
362
499
  # Extracts a name or symbol from the token stream.
363
500
 
@@ -385,6 +522,20 @@ class RDoc::Parser::Ruby < RDoc::Parser
385
522
  end
386
523
  end
387
524
 
525
+ def stop_at_EXPR_END # :nodoc:
526
+ @scanner.lex_state == :EXPR_END || !@scanner.continue
527
+ end
528
+
529
+ ##
530
+ # Marks containers between +container+ and +ancestor+ as ignored
531
+
532
+ def suppress_parents container, ancestor # :nodoc:
533
+ while container and container != ancestor do
534
+ container.suppress unless container.documented?
535
+ container = container.parent
536
+ end
537
+ end
538
+
388
539
  ##
389
540
  # Look for directives in a normal comment block:
390
541
  #
@@ -450,16 +601,11 @@ class RDoc::Parser::Ruby < RDoc::Parser
450
601
  unget_tk tk
451
602
  end
452
603
 
453
- att = RDoc::Attr.new get_tkread, name, rw, comment, single == SINGLE
454
- att.record_location @top_level
604
+ att = create_attr context, single, name, rw, comment
455
605
  att.offset = offset
456
606
  att.line = line_no
457
607
 
458
608
  read_documentation_modifiers att, RDoc::ATTR_MODIFIERS
459
-
460
- context.add_attribute att
461
-
462
- @stats.add_attribute att
463
609
  else
464
610
  warn "'attr' ignored - looks like a variable"
465
611
  end
@@ -480,7 +626,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
480
626
  read_documentation_modifiers tmp, RDoc::ATTR_MODIFIERS
481
627
  # TODO In most other places we let the context keep track of document_self
482
628
  # and add found items appropriately but here we do not. I'm not sure why.
483
- return unless tmp.document_self
629
+ return if @track_visibility and not tmp.document_self
484
630
 
485
631
  case tk.name
486
632
  when "attr_reader" then rw = "R"
@@ -491,13 +637,9 @@ class RDoc::Parser::Ruby < RDoc::Parser
491
637
  end
492
638
 
493
639
  for name in args
494
- att = RDoc::Attr.new get_tkread, name, rw, comment, single == SINGLE
495
- att.record_location @top_level
640
+ att = create_attr context, single, name, rw, comment
496
641
  att.offset = offset
497
642
  att.line = line_no
498
-
499
- context.add_attribute att
500
- @stats.add_attribute att
501
643
  end
502
644
  end
503
645
 
@@ -517,7 +659,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
517
659
 
518
660
  new_name = get_symbol_or_name
519
661
 
520
- @scanner.instance_eval { @lex_state = EXPR_FNAME }
662
+ @scanner.lex_state = :EXPR_FNAME
521
663
 
522
664
  skip_tkspace
523
665
  if TkCOMMA === peek_tk then
@@ -533,7 +675,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
533
675
 
534
676
  al = RDoc::Alias.new(get_tkread, old_name, new_name, comment,
535
677
  single == SINGLE)
536
- al.record_location @top_level
678
+ record_location al
537
679
  al.offset = offset
538
680
  al.line = line_no
539
681
 
@@ -567,7 +709,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
567
709
  when end_token
568
710
  if end_token == TkRPAREN
569
711
  nest -= 1
570
- break if @scanner.lex_state == EXPR_END and nest <= 0
712
+ break if @scanner.lex_state == :EXPR_END and nest <= 0
571
713
  else
572
714
  break unless @scanner.continue
573
715
  end
@@ -579,9 +721,8 @@ class RDoc::Parser::Ruby < RDoc::Parser
579
721
  end
580
722
  tk = get_tk
581
723
  end
582
- res = get_tkread.tr("\n", " ").strip
583
- res = "" if res == ";"
584
- res
724
+
725
+ get_tkread_clean "\n", " "
585
726
  end
586
727
 
587
728
  ##
@@ -594,79 +735,105 @@ class RDoc::Parser::Ruby < RDoc::Parser
594
735
  declaration_context = container
595
736
  container, name_t, given_name = get_class_or_module container
596
737
 
597
- case name_t
598
- when TkCONSTANT
599
- name = name_t.name
600
- superclass = '::Object'
601
-
602
- if given_name =~ /^::/ then
603
- declaration_context = @top_level
604
- given_name = $'
738
+ cls =
739
+ case name_t
740
+ when TkCONSTANT
741
+ parse_class_regular container, declaration_context, single,
742
+ name_t, given_name, comment
743
+ when TkLSHFT
744
+ case name = get_class_specification
745
+ when 'self', container.name
746
+ parse_statements container, SINGLE
747
+ return # don't update offset or line
748
+ else
749
+ parse_class_singleton container, name, comment
750
+ end
751
+ else
752
+ warn "Expected class name or '<<'. Got #{name_t.class}: #{name_t.text.inspect}"
753
+ return
605
754
  end
606
755
 
607
- if TkLT === peek_tk then
608
- get_tk
609
- skip_tkspace
610
- superclass = get_class_specification
611
- superclass = '(unknown)' if superclass.empty?
612
- end
756
+ cls.offset = offset
757
+ cls.line = line_no
758
+
759
+ cls
760
+ end
613
761
 
614
- cls_type = single == SINGLE ? RDoc::SingleClass : RDoc::NormalClass
615
- cls = declaration_context.add_class cls_type, given_name, superclass
616
- cls.ignore unless container.document_children
762
+ ##
763
+ # Parses and creates a regular class
617
764
 
618
- read_documentation_modifiers cls, RDoc::CLASS_MODIFIERS
619
- cls.record_location @top_level
620
- cls.offset = offset
621
- cls.line = line_no
765
+ def parse_class_regular container, declaration_context, single, # :nodoc:
766
+ name_t, given_name, comment
767
+ superclass = '::Object'
622
768
 
623
- cls.add_comment comment, @top_level
769
+ if given_name =~ /^::/ then
770
+ declaration_context = @top_level
771
+ given_name = $'
772
+ end
624
773
 
625
- @top_level.add_to_classes_or_modules cls
626
- @stats.add_class cls
774
+ if TkLT === peek_tk then
775
+ get_tk
776
+ skip_tkspace
777
+ superclass = get_class_specification
778
+ superclass = '(unknown)' if superclass.empty?
779
+ end
627
780
 
628
- parse_statements cls
629
- when TkLSHFT
630
- case name = get_class_specification
631
- when 'self', container.name
632
- parse_statements container, SINGLE
633
- else
634
- other = @store.find_class_named name
781
+ cls_type = single == SINGLE ? RDoc::SingleClass : RDoc::NormalClass
782
+ cls = declaration_context.add_class cls_type, given_name, superclass
783
+ cls.ignore unless container.document_children
635
784
 
636
- unless other then
637
- if name =~ /^::/ then
638
- name = $'
639
- container = @top_level
640
- end
785
+ read_documentation_modifiers cls, RDoc::CLASS_MODIFIERS
786
+ record_location cls
641
787
 
642
- other = container.add_module RDoc::NormalModule, name
643
- other.record_location @top_level
644
- other.offset = offset
645
- other.line = line_no
788
+ cls.add_comment comment, @top_level
646
789
 
647
- # class << $gvar
648
- other.ignore if name.empty?
790
+ @top_level.add_to_classes_or_modules cls
791
+ @stats.add_class cls
649
792
 
650
- other.add_comment comment, @top_level
651
- end
793
+ suppress_parents container, declaration_context unless cls.document_self
652
794
 
653
- # notify :nodoc: all if not a constant-named class/module
654
- # (and remove any comment)
655
- unless name =~ /\A(::)?[A-Z]/ then
656
- other.document_self = nil
657
- other.document_children = false
658
- other.clear_comment
659
- end
795
+ parse_statements cls
796
+
797
+ cls
798
+ end
799
+
800
+ ##
801
+ # Parses a singleton class in +container+ with the given +name+ and
802
+ # +comment+.
660
803
 
661
- @top_level.add_to_classes_or_modules other
662
- @stats.add_class other
804
+ def parse_class_singleton container, name, comment # :nodoc:
805
+ other = @store.find_class_named name
663
806
 
664
- read_documentation_modifiers other, RDoc::CLASS_MODIFIERS
665
- parse_statements(other, SINGLE)
807
+ unless other then
808
+ if name =~ /^::/ then
809
+ name = $'
810
+ container = @top_level
666
811
  end
667
- else
668
- warn("Expected class name or '<<'. Got #{name_t.class}: #{name_t.text.inspect}")
812
+
813
+ other = container.add_module RDoc::NormalModule, name
814
+ record_location other
815
+
816
+ # class << $gvar
817
+ other.ignore if name.empty?
818
+
819
+ other.add_comment comment, @top_level
820
+ end
821
+
822
+ # notify :nodoc: all if not a constant-named class/module
823
+ # (and remove any comment)
824
+ unless name =~ /\A(::)?[A-Z]/ then
825
+ other.document_self = nil
826
+ other.document_children = false
827
+ other.clear_comment
669
828
  end
829
+
830
+ @top_level.add_to_classes_or_modules other
831
+ @stats.add_class other
832
+
833
+ read_documentation_modifiers other, RDoc::CLASS_MODIFIERS
834
+ parse_statements(other, SINGLE)
835
+
836
+ other
670
837
  end
671
838
 
672
839
  ##
@@ -674,6 +841,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
674
841
  # true, no found constants will be added to RDoc.
675
842
 
676
843
  def parse_constant container, tk, comment, ignore_constants = false
844
+ prev_container = container
677
845
  offset = tk.seek
678
846
  line_no = tk.line_no
679
847
 
@@ -696,25 +864,44 @@ class RDoc::Parser::Ruby < RDoc::Parser
696
864
  end
697
865
 
698
866
  unless TkASSIGN === eq_tk then
867
+ suppress_parents container, prev_container
868
+
699
869
  unget_tk eq_tk
700
870
  return false
701
871
  end
702
872
 
873
+ if TkGT === peek_tk then
874
+ unget_tk eq_tk
875
+ return
876
+ end
877
+
703
878
  value = ''
704
879
  con = RDoc::Constant.new name, value, comment
705
- nest = 0
706
- get_tkread
707
880
 
708
- tk = get_tk
881
+ body = parse_constant_body container, con
709
882
 
710
- if TkGT === tk then
711
- unget_tk tk
712
- unget_tk eq_tk
713
- return false
714
- end
883
+ return unless body
884
+
885
+ value.replace body
886
+ record_location con
887
+ con.offset = offset
888
+ con.line = line_no
889
+ read_documentation_modifiers con, RDoc::CONSTANT_MODIFIERS
890
+
891
+ @stats.add_constant con
892
+ con = container.add_constant con
893
+
894
+ true
895
+ end
715
896
 
897
+ def parse_constant_body container, constant # :nodoc:
898
+ nest = 0
716
899
  rhs_name = ''
717
900
 
901
+ get_tkread
902
+
903
+ tk = get_tk
904
+
718
905
  loop do
719
906
  case tk
720
907
  when TkSEMICOLON then
@@ -725,30 +912,22 @@ class RDoc::Parser::Ruby < RDoc::Parser
725
912
  when TkRPAREN, TkRBRACE, TkRBRACK, TkEND then
726
913
  nest -= 1
727
914
  when TkCOMMENT then
728
- if nest <= 0 &&
729
- (@scanner.lex_state == EXPR_END || !@scanner.continue) then
915
+ if nest <= 0 and stop_at_EXPR_END then
730
916
  unget_tk tk
731
917
  break
732
918
  else
733
919
  unget_tk tk
734
- read_documentation_modifiers con, RDoc::CONSTANT_MODIFIERS
920
+ read_documentation_modifiers constant, RDoc::CONSTANT_MODIFIERS
735
921
  end
736
922
  when TkCONSTANT then
737
923
  rhs_name << tk.name
738
924
 
739
925
  if nest <= 0 and TkNL === peek_tk then
740
- mod = if rhs_name =~ /^::/ then
741
- @store.find_class_or_module rhs_name
742
- else
743
- container.find_module_named rhs_name
744
- end
745
-
746
- container.add_module_alias mod, name, @top_level if mod
926
+ create_module_alias container, constant, rhs_name
747
927
  break
748
928
  end
749
929
  when TkNL then
750
- if nest <= 0 &&
751
- (@scanner.lex_state == EXPR_END || !@scanner.continue) then
930
+ if nest <= 0 and stop_at_EXPR_END then
752
931
  unget_tk tk
753
932
  break
754
933
  end
@@ -760,19 +939,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
760
939
  tk = get_tk
761
940
  end
762
941
 
763
- res = get_tkread.gsub(/^[ \t]+/, '').strip
764
- res = "" if res == ";"
765
-
766
- value.replace res
767
- con.record_location @top_level
768
- con.offset = offset
769
- con.line = line_no
770
- read_documentation_modifiers con, RDoc::CONSTANT_MODIFIERS
771
-
772
- @stats.add_constant con
773
- con = container.add_constant con
774
-
775
- true
942
+ get_tkread_clean(/^[ \t]+/, '')
776
943
  end
777
944
 
778
945
  ##
@@ -789,56 +956,72 @@ class RDoc::Parser::Ruby < RDoc::Parser
789
956
 
790
957
  singleton = !!text.sub!(/(^# +:?)(singleton-)(method:)/, '\1\3')
791
958
 
792
- # REFACTOR
793
- if text.sub!(/^# +:?method: *(\S*).*?\n/i, '') then
794
- name = $1 unless $1.empty?
959
+ co =
960
+ if text.sub!(/^# +:?method: *(\S*).*?\n/i, '') then
961
+ parse_comment_ghost container, text, $1, column, line_no, comment
962
+ elsif text.sub!(/# +:?(attr(_reader|_writer|_accessor)?): *(\S*).*?\n/i, '') then
963
+ parse_comment_attr container, $1, $3, comment
964
+ end
795
965
 
796
- meth = RDoc::GhostMethod.new get_tkread, name
797
- meth.record_location @top_level
798
- meth.singleton = singleton
799
- meth.offset = offset
800
- meth.line = line_no
966
+ if co then
967
+ co.singleton = singleton
968
+ co.offset = offset
969
+ co.line = line_no
970
+ end
801
971
 
802
- meth.start_collecting_tokens
803
- indent = TkSPACE.new 0, 1, 1
804
- indent.set_text " " * column
972
+ true
973
+ end
805
974
 
806
- position_comment = TkCOMMENT.new 0, line_no, 1
807
- position_comment.set_text "# File #{@top_level.relative_name}, line #{line_no}"
808
- meth.add_tokens [position_comment, NEWLINE_TOKEN, indent]
975
+ ##
976
+ # Parse a comment that is describing an attribute in +container+ with the
977
+ # given +name+ and +comment+.
809
978
 
810
- meth.params = ''
979
+ def parse_comment_attr container, type, name, comment # :nodoc:
980
+ return if name.empty?
811
981
 
812
- comment.normalize
813
- comment.extract_call_seq meth
982
+ rw = case type
983
+ when 'attr_reader' then 'R'
984
+ when 'attr_writer' then 'W'
985
+ else 'RW'
986
+ end
814
987
 
815
- return unless meth.name
988
+ create_attr container, NORMAL, name, rw, comment
989
+ end
816
990
 
817
- container.add_method meth
991
+ def parse_comment_ghost container, text, name, column, line_no, # :nodoc:
992
+ comment
993
+ name = nil if name.empty?
818
994
 
819
- meth.comment = comment
995
+ meth = RDoc::GhostMethod.new get_tkread, name
996
+ record_location meth
820
997
 
821
- @stats.add_method meth
822
- elsif text.sub!(/# +:?(attr(_reader|_writer|_accessor)?): *(\S*).*?\n/i, '') then
823
- rw = case $1
824
- when 'attr_reader' then 'R'
825
- when 'attr_writer' then 'W'
826
- else 'RW'
827
- end
998
+ meth.start_collecting_tokens
999
+ indent = TkSPACE.new 0, 1, 1
1000
+ indent.set_text " " * column
828
1001
 
829
- name = $3 unless $3.empty?
1002
+ position_comment = TkCOMMENT.new 0, line_no, 1
1003
+ position_comment.set_text "# File #{@top_level.relative_name}, line #{line_no}"
1004
+ meth.add_tokens [position_comment, NEWLINE_TOKEN, indent]
830
1005
 
831
- # TODO authorize 'singleton-attr...'?
832
- att = RDoc::Attr.new get_tkread, name, rw, comment
833
- att.record_location @top_level
834
- att.offset = offset
835
- att.line = line_no
1006
+ meth.params =
1007
+ if text.sub!(/^#\s+:?args?:\s*(.*?)\s*$/i, '') then
1008
+ $1
1009
+ else
1010
+ ''
1011
+ end
836
1012
 
837
- container.add_attribute att
838
- @stats.add_attribute att
839
- end
1013
+ comment.normalize
1014
+ comment.extract_call_seq meth
840
1015
 
841
- true
1016
+ return unless meth.name
1017
+
1018
+ container.add_method meth
1019
+
1020
+ meth.comment = comment
1021
+
1022
+ @stats.add_method meth
1023
+
1024
+ meth
842
1025
  end
843
1026
 
844
1027
  ##
@@ -853,7 +1036,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
853
1036
  name, = signature.split %r%[ \(]%, 2
854
1037
 
855
1038
  meth = RDoc::GhostMethod.new get_tkread, name
856
- meth.record_location @top_level
1039
+ record_location meth
857
1040
  meth.offset = offset
858
1041
  meth.line = line_no
859
1042
 
@@ -879,17 +1062,18 @@ class RDoc::Parser::Ruby < RDoc::Parser
879
1062
  end
880
1063
 
881
1064
  ##
882
- # Parses an +include+ in +context+ with +comment+
1065
+ # Parses an +include+ or +extend+, indicated by the +klass+ and adds it to
1066
+ # +container+ # with +comment+
883
1067
 
884
- def parse_include context, comment
1068
+ def parse_extend_or_include klass, container, comment # :nodoc:
885
1069
  loop do
886
1070
  skip_tkspace_comment
887
1071
 
888
1072
  name = get_constant_with_optional_parens
889
1073
 
890
1074
  unless name.empty? then
891
- incl = context.add_include RDoc::Include.new(name, comment)
892
- incl.record_location @top_level
1075
+ obj = container.add klass, name, comment
1076
+ record_location obj
893
1077
  end
894
1078
 
895
1079
  return unless TkCOMMA === peek_tk
@@ -899,23 +1083,40 @@ class RDoc::Parser::Ruby < RDoc::Parser
899
1083
  end
900
1084
 
901
1085
  ##
902
- # Parses an +extend+ in +context+ with +comment+
903
-
904
- def parse_extend context, comment
905
- loop do
906
- skip_tkspace_comment
907
-
908
- name = get_constant_with_optional_parens
1086
+ # Parses identifiers that can create new methods or change visibility.
1087
+ #
1088
+ # Returns true if the comment was not consumed.
909
1089
 
910
- unless name.empty? then
911
- incl = context.add_extend RDoc::Extend.new(name, comment)
912
- incl.record_location @top_level
1090
+ def parse_identifier container, single, tk, comment # :nodoc:
1091
+ case tk.name
1092
+ when 'private', 'protected', 'public', 'private_class_method',
1093
+ 'public_class_method', 'module_function' then
1094
+ parse_visibility container, single, tk
1095
+ return true
1096
+ when 'attr' then
1097
+ parse_attr container, single, tk, comment
1098
+ when /^attr_(reader|writer|accessor)$/ then
1099
+ parse_attr_accessor container, single, tk, comment
1100
+ when 'alias_method' then
1101
+ parse_alias container, single, tk, comment
1102
+ when 'require', 'include' then
1103
+ # ignore
1104
+ else
1105
+ if comment.text =~ /\A#\#$/ then
1106
+ case comment.text
1107
+ when /^# +:?attr(_reader|_writer|_accessor)?:/ then
1108
+ parse_meta_attr container, single, tk, comment
1109
+ else
1110
+ method = parse_meta_method container, single, tk, comment
1111
+ method.params = container.params if
1112
+ container.params
1113
+ method.block_params = container.block_params if
1114
+ container.block_params
1115
+ end
913
1116
  end
914
-
915
- return unless TkCOMMA === peek_tk
916
-
917
- get_tk
918
1117
  end
1118
+
1119
+ false
919
1120
  end
920
1121
 
921
1122
  ##
@@ -966,19 +1167,10 @@ class RDoc::Parser::Ruby < RDoc::Parser
966
1167
  end
967
1168
 
968
1169
  if name then
969
- att = RDoc::Attr.new get_tkread, name, rw, comment, single == SINGLE
970
- att.record_location @top_level
971
-
972
- context.add_attribute att
973
- @stats.add_attribute att
1170
+ att = create_attr context, single, name, rw, comment
974
1171
  else
975
1172
  args.each do |attr_name|
976
- att = RDoc::Attr.new(get_tkread, attr_name, rw, comment,
977
- single == SINGLE)
978
- att.record_location @top_level
979
-
980
- context.add_attribute att
981
- @stats.add_attribute att
1173
+ att = create_attr context, single, attr_name, rw, comment
982
1174
  end
983
1175
  end
984
1176
 
@@ -1001,28 +1193,12 @@ class RDoc::Parser::Ruby < RDoc::Parser
1001
1193
 
1002
1194
  singleton = !!comment.text.sub!(/(^# +:?)(singleton-)(method:)/, '\1\3')
1003
1195
 
1004
- if comment.text.sub!(/^# +:?method: *(\S*).*?\n/i, '') then
1005
- name = $1 unless $1.empty?
1006
- end
1196
+ name = parse_meta_method_name comment, tk
1007
1197
 
1008
- if name.nil? then
1009
- name_t = get_tk
1010
- case name_t
1011
- when TkSYMBOL then
1012
- name = name_t.text[1..-1]
1013
- when TkSTRING then
1014
- name = name_t.value[1..-2]
1015
- when TkASSIGN then # ignore
1016
- remove_token_listener self
1017
- return
1018
- else
1019
- warn "unknown name token #{name_t.inspect} for meta-method '#{tk.name}'"
1020
- name = 'unknown'
1021
- end
1022
- end
1198
+ return unless name
1023
1199
 
1024
1200
  meth = RDoc::MetaMethod.new get_tkread, name
1025
- meth.record_location @top_level
1201
+ record_location meth
1026
1202
  meth.offset = offset
1027
1203
  meth.line = line_no
1028
1204
  meth.singleton = singleton
@@ -1038,6 +1214,46 @@ class RDoc::Parser::Ruby < RDoc::Parser
1038
1214
  meth.add_tokens [position_comment, NEWLINE_TOKEN, indent]
1039
1215
  meth.add_tokens @token_stream
1040
1216
 
1217
+ parse_meta_method_params container, single, meth, tk, comment
1218
+
1219
+ meth.comment = comment
1220
+
1221
+ @stats.add_method meth
1222
+
1223
+ meth
1224
+ end
1225
+
1226
+ ##
1227
+ # Parses the name of a metaprogrammed method. +comment+ is used to
1228
+ # determine the name while +tk+ is used in an error message if the name
1229
+ # cannot be determined.
1230
+
1231
+ def parse_meta_method_name comment, tk # :nodoc:
1232
+ if comment.text.sub!(/^# +:?method: *(\S*).*?\n/i, '') then
1233
+ return $1 unless $1.empty?
1234
+ end
1235
+
1236
+ name_t = get_tk
1237
+
1238
+ case name_t
1239
+ when TkSYMBOL then
1240
+ name_t.text[1..-1]
1241
+ when TkSTRING then
1242
+ name_t.value[1..-2]
1243
+ when TkASSIGN then # ignore
1244
+ remove_token_listener self
1245
+
1246
+ nil
1247
+ else
1248
+ warn "unknown name token #{name_t.inspect} for meta-method '#{tk.name}'"
1249
+ 'unknown'
1250
+ end
1251
+ end
1252
+
1253
+ ##
1254
+ # Parses the parameters and block for a meta-programmed method.
1255
+
1256
+ def parse_meta_method_params container, single, meth, tk, comment # :nodoc:
1041
1257
  token_listener meth do
1042
1258
  meth.params = ''
1043
1259
 
@@ -1064,20 +1280,14 @@ class RDoc::Parser::Ruby < RDoc::Parser
1064
1280
  end
1065
1281
  end
1066
1282
  end
1067
-
1068
- meth.comment = comment
1069
-
1070
- @stats.add_method meth
1071
-
1072
- meth
1073
1283
  end
1074
1284
 
1075
1285
  ##
1076
1286
  # Parses a normal method defined by +def+
1077
1287
 
1078
1288
  def parse_method(container, single, tk, comment)
1079
- added_container = nil
1080
- meth = nil
1289
+ singleton = nil
1290
+ added_container = false
1081
1291
  name = nil
1082
1292
  column = tk.char_no
1083
1293
  offset = tk.seek
@@ -1087,110 +1297,17 @@ class RDoc::Parser::Ruby < RDoc::Parser
1087
1297
  add_token tk
1088
1298
 
1089
1299
  token_listener self do
1090
- @scanner.instance_eval do @lex_state = EXPR_FNAME end
1091
-
1092
- skip_tkspace
1093
- name_t = get_tk
1094
- back_tk = skip_tkspace
1095
- meth = nil
1096
- added_container = false
1097
-
1098
- case dot = get_tk
1099
- when TkDOT, TkCOLON2 then
1100
- @scanner.instance_eval do @lex_state = EXPR_FNAME end
1101
- skip_tkspace
1102
- name_t2 = get_tk
1103
-
1104
- case name_t
1105
- when TkSELF, TkMOD then
1106
- name = case name_t2
1107
- # NOTE: work around '[' being consumed early and not being
1108
- # re-tokenized as a TkAREF
1109
- when TkfLBRACK then
1110
- get_tk
1111
- '[]'
1112
- else
1113
- name_t2.name
1114
- end
1115
- when TkCONSTANT then
1116
- name = name_t2.name
1117
- prev_container = container
1118
- container = container.find_module_named(name_t.name)
1119
-
1120
- unless container then
1121
- constant = prev_container.constants.find do |const|
1122
- const.name == name_t.name
1123
- end
1124
-
1125
- if constant then
1126
- parse_method_dummy prev_container
1127
- return
1128
- end
1129
- end
1130
-
1131
- unless container then
1132
- added_container = true
1133
- obj = name_t.name.split("::").inject(Object) do |state, item|
1134
- state.const_get(item)
1135
- end rescue nil
1136
-
1137
- type = obj.class == Class ? RDoc::NormalClass : RDoc::NormalModule
1138
-
1139
- unless [Class, Module].include?(obj.class) then
1140
- warn("Couldn't find #{name_t.name}. Assuming it's a module")
1141
- end
1142
-
1143
- if type == RDoc::NormalClass then
1144
- sclass = obj.superclass ? obj.superclass.name : nil
1145
- container = prev_container.add_class type, name_t.name, sclass
1146
- else
1147
- container = prev_container.add_module type, name_t.name
1148
- end
1149
-
1150
- container.record_location @top_level
1151
- end
1152
- when TkIDENTIFIER, TkIVAR, TkGVAR then
1153
- parse_method_dummy container
1154
- return
1155
- when TkTRUE, TkFALSE, TkNIL then
1156
- klass_name = "#{name_t.name.capitalize}Class"
1157
- container = @store.find_class_named klass_name
1158
- container ||= @top_level.add_class RDoc::NormalClass, klass_name
1159
-
1160
- name = name_t2.name
1161
- else
1162
- warn "unexpected method name token #{name_t.inspect}"
1163
- # break
1164
- skip_method container
1165
- return
1166
- end
1300
+ prev_container = container
1301
+ name, container, singleton = parse_method_name container
1302
+ added_container = container != prev_container
1303
+ end
1167
1304
 
1168
- meth = RDoc::AnyMethod.new(get_tkread, name)
1169
- meth.singleton = true
1170
- else
1171
- unget_tk dot
1172
- back_tk.reverse_each do |token|
1173
- unget_tk token
1174
- end
1305
+ return unless name
1175
1306
 
1176
- name = case name_t
1177
- when TkSTAR, TkAMPER then
1178
- name_t.text
1179
- else
1180
- unless name_t.respond_to? :name then
1181
- warn "expected method name token, . or ::, got #{name_t.inspect}"
1182
- skip_method container
1183
- return
1184
- end
1185
- name_t.name
1186
- end
1187
-
1188
- meth = RDoc::AnyMethod.new get_tkread, name
1189
- meth.singleton = (single == SINGLE)
1190
- end
1191
- end
1307
+ meth = RDoc::AnyMethod.new get_tkread, name
1308
+ meth.singleton = singleton
1192
1309
 
1193
- meth.record_location @top_level
1310
+ record_location meth
1194
1311
  meth.offset = offset
1195
1312
  meth.line = line_no
1196
1313
 
@@ -1203,11 +1320,25 @@ class RDoc::Parser::Ruby < RDoc::Parser
1203
1320
  meth.add_tokens [token, NEWLINE_TOKEN, indent]
1204
1321
  meth.add_tokens @token_stream
1205
1322
 
1323
+ parse_method_params_and_body container, single, meth, added_container
1324
+
1325
+ comment.normalize
1326
+ comment.extract_call_seq meth
1327
+
1328
+ meth.comment = comment
1329
+
1330
+ @stats.add_method meth
1331
+ end
1332
+
1333
+ ##
1334
+ # Parses the parameters and body of +meth+
1335
+
1336
+ def parse_method_params_and_body container, single, meth, added_container
1206
1337
  token_listener meth do
1207
- @scanner.instance_eval do @continue = false end
1338
+ @scanner.continue = false
1208
1339
  parse_method_parameters meth
1209
1340
 
1210
- if meth.document_self then
1341
+ if meth.document_self or not @track_visibility then
1211
1342
  container.add_method meth
1212
1343
  elsif added_container then
1213
1344
  container.document_self = false
@@ -1216,7 +1347,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
1216
1347
  # Having now read the method parameters and documentation modifiers, we
1217
1348
  # now know whether we have to rename #initialize to ::new
1218
1349
 
1219
- if name == "initialize" && !meth.singleton then
1350
+ if meth.name == "initialize" && !meth.singleton then
1220
1351
  if meth.dont_rename_initialize then
1221
1352
  meth.visibility = :protected
1222
1353
  else
@@ -1228,13 +1359,6 @@ class RDoc::Parser::Ruby < RDoc::Parser
1228
1359
 
1229
1360
  parse_statements container, single, meth
1230
1361
  end
1231
-
1232
- comment.normalize
1233
- comment.extract_call_seq meth
1234
-
1235
- meth.comment = comment
1236
-
1237
- @stats.add_method meth
1238
1362
  end
1239
1363
 
1240
1364
  ##
@@ -1247,6 +1371,106 @@ class RDoc::Parser::Ruby < RDoc::Parser
1247
1371
  skip_method dummy
1248
1372
  end
1249
1373
 
1374
+ ##
1375
+ # Parses the name of a method in +container+.
1376
+ #
1377
+ # Returns the method name, the container it is in (for def Foo.name) and if
1378
+ # it is a singleton or regular method.
1379
+
1380
+ def parse_method_name container # :nodoc:
1381
+ @scanner.lex_state = :EXPR_FNAME
1382
+
1383
+ skip_tkspace
1384
+ name_t = get_tk
1385
+ back_tk = skip_tkspace
1386
+ singleton = false
1387
+
1388
+ case dot = get_tk
1389
+ when TkDOT, TkCOLON2 then
1390
+ singleton = true
1391
+
1392
+ name, container = parse_method_name_singleton container, name_t
1393
+ else
1394
+ unget_tk dot
1395
+ back_tk.reverse_each do |token|
1396
+ unget_tk token
1397
+ end
1398
+
1399
+ name = parse_method_name_regular container, name_t
1400
+ end
1401
+
1402
+ return name, container, singleton
1403
+ end
1404
+
1405
+ ##
1406
+ # For the given +container+ and initial name token +name_t+ the method name
1407
+ # is parsed from the token stream for a regular method.
1408
+
1409
+ def parse_method_name_regular container, name_t # :nodoc:
1410
+ case name_t
1411
+ when TkSTAR, TkAMPER then
1412
+ name_t.text
1413
+ else
1414
+ unless name_t.respond_to? :name then
1415
+ warn "expected method name token, . or ::, got #{name_t.inspect}"
1416
+ skip_method container
1417
+ return
1418
+ end
1419
+ name_t.name
1420
+ end
1421
+ end
1422
+
1423
+ ##
1424
+ # For the given +container+ and initial name token +name_t+ the method name
1425
+ # and the new +container+ (if necessary) are parsed from the token stream
1426
+ # for a singleton method.
1427
+
1428
+ def parse_method_name_singleton container, name_t # :nodoc:
1429
+ @scanner.lex_state = :EXPR_FNAME
1430
+ skip_tkspace
1431
+ name_t2 = get_tk
1432
+
1433
+ name =
1434
+ case name_t
1435
+ when TkSELF, TkMOD then
1436
+ case name_t2
1437
+ # NOTE: work around '[' being consumed early and not being re-tokenized
1438
+ # as a TkAREF
1439
+ when TkfLBRACK then
1440
+ get_tk
1441
+ '[]'
1442
+ else
1443
+ name_t2.name
1444
+ end
1445
+ when TkCONSTANT then
1446
+ name = name_t2.name
1447
+
1448
+ container = get_method_container container, name_t
1449
+
1450
+ return unless container
1451
+
1452
+ name
1453
+ when TkIDENTIFIER, TkIVAR, TkGVAR then
1454
+ parse_method_dummy container
1455
+
1456
+ nil
1457
+ when TkTRUE, TkFALSE, TkNIL then
1458
+ klass_name = "#{name_t.name.capitalize}Class"
1459
+ container = @store.find_class_named klass_name
1460
+ container ||= @top_level.add_class RDoc::NormalClass, klass_name
1461
+
1462
+ name_t2.name
1463
+ else
1464
+ warn "unexpected method name token #{name_t.inspect}"
1465
+ # break
1466
+ skip_method container
1467
+
1468
+ nil
1469
+ end
1470
+
1471
+ return name, container
1472
+ end
1473
+
1250
1474
  ##
1251
1475
  # Extracts +yield+ parameters from +method+
1252
1476
 
@@ -1254,20 +1478,9 @@ class RDoc::Parser::Ruby < RDoc::Parser
1254
1478
  modifiers = RDoc::METHOD_MODIFIERS)
1255
1479
  skip_tkspace false
1256
1480
  tk = get_tk
1481
+ end_token = get_end_token tk
1482
+ return '' unless end_token
1257
1483
 
1258
- # Little hack going on here. In the statement
1259
- # f = 2*(1+yield)
1260
- # We see the RPAREN as the next token, so we need
1261
- # to exit early. This still won't catch all cases
1262
- # (such as "a = yield + 1"
1263
- end_token = case tk
1264
- when TkLPAREN, TkfLPAREN
1265
- TkRPAREN
1266
- when TkRPAREN
1267
- return ""
1268
- else
1269
- TkNL
1270
- end
1271
1484
  nest = 0
1272
1485
 
1273
1486
  loop do
@@ -1306,9 +1519,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
1306
1519
  tk = get_tk
1307
1520
  end
1308
1521
 
1309
- res = get_tkread.gsub(/\s+/, ' ').strip
1310
- res = '' if res == ';'
1311
- res
1522
+ get_tkread_clean(/\s+/, ' ')
1312
1523
  end
1313
1524
 
1314
1525
  ##
@@ -1341,13 +1552,12 @@ class RDoc::Parser::Ruby < RDoc::Parser
1341
1552
 
1342
1553
  mod = container.add_module RDoc::NormalModule, name
1343
1554
  mod.ignore unless container.document_children
1344
- mod.record_location @top_level
1555
+ record_location mod
1345
1556
 
1346
1557
  read_documentation_modifiers mod, RDoc::CLASS_MODIFIERS
1347
1558
  mod.add_comment comment, @top_level
1348
1559
  parse_statements mod
1349
1560
 
1350
- @top_level.add_to_classes_or_modules mod
1351
1561
  @stats.add_module mod
1352
1562
  end
1353
1563
 
@@ -1393,7 +1603,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
1393
1603
  end
1394
1604
 
1395
1605
  ##
1396
- # The core of the ruby parser.
1606
+ # The core of the Ruby parser.
1397
1607
 
1398
1608
  def parse_statements(container, single = NORMAL, current_method = nil,
1399
1609
  comment = new_comment(''))
@@ -1443,6 +1653,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
1443
1653
  look_for_directives_in container, comment
1444
1654
 
1445
1655
  if container.done_documenting then
1656
+ throw :eof if RDoc::TopLevel === container
1446
1657
  container.ongoing_visibility = save_visibility
1447
1658
  end
1448
1659
  end
@@ -1504,42 +1715,16 @@ class RDoc::Parser::Ruby < RDoc::Parser
1504
1715
 
1505
1716
  when TkIDENTIFIER then
1506
1717
  if nest == 1 and current_method.nil? then
1507
- case tk.name
1508
- when 'private', 'protected', 'public', 'private_class_method',
1509
- 'public_class_method', 'module_function' then
1510
- parse_visibility container, single, tk
1511
- keep_comment = true
1512
- when 'attr' then
1513
- parse_attr container, single, tk, comment
1514
- when /^attr_(reader|writer|accessor)$/ then
1515
- parse_attr_accessor container, single, tk, comment
1516
- when 'alias_method' then
1517
- parse_alias container, single, tk, comment
1518
- when 'require', 'include' then
1519
- # ignore
1520
- else
1521
- if comment.text =~ /\A#\#$/ then
1522
- case comment.text
1523
- when /^# +:?attr(_reader|_writer|_accessor)?:/ then
1524
- parse_meta_attr container, single, tk, comment
1525
- else
1526
- method = parse_meta_method container, single, tk, comment
1527
- method.params = container.params if
1528
- container.params
1529
- method.block_params = container.block_params if
1530
- container.block_params
1531
- end
1532
- end
1533
- end
1718
+ keep_comment = parse_identifier container, single, tk, comment
1534
1719
  end
1535
1720
 
1536
1721
  case tk.name
1537
1722
  when "require" then
1538
1723
  parse_require container, comment
1539
1724
  when "include" then
1540
- parse_include container, comment
1725
+ parse_extend_or_include RDoc::Include, container, comment
1541
1726
  when "extend" then
1542
- parse_extend container, comment
1727
+ parse_extend_or_include RDoc::Extend, container, comment
1543
1728
  end
1544
1729
 
1545
1730
  when TkEND then
@@ -1570,10 +1755,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
1570
1755
  container.block_params = nil
1571
1756
  end
1572
1757
 
1573
- begin
1574
- get_tkread
1575
- skip_tkspace false
1576
- end while peek_tk == TkNL
1758
+ consume_trailing_spaces
1577
1759
  end
1578
1760
 
1579
1761
  container.params = nil
@@ -1584,50 +1766,70 @@ class RDoc::Parser::Ruby < RDoc::Parser
1584
1766
  # Parse up to +no+ symbol arguments
1585
1767
 
1586
1768
  def parse_symbol_arg(no = nil)
1587
- args = []
1588
-
1589
1769
  skip_tkspace_comment
1590
1770
 
1591
1771
  case tk = get_tk
1592
1772
  when TkLPAREN
1593
- loop do
1594
- skip_tkspace_comment
1595
- if tk1 = parse_symbol_in_arg
1596
- args.push tk1
1597
- break if no and args.size >= no
1598
- end
1773
+ parse_symbol_arg_paren no
1774
+ else
1775
+ parse_symbol_arg_space no, tk
1776
+ end
1777
+ end
1599
1778
 
1600
- skip_tkspace_comment
1601
- case tk2 = get_tk
1602
- when TkRPAREN
1603
- break
1604
- when TkCOMMA
1605
- else
1606
- warn("unexpected token: '#{tk2.inspect}'") if $DEBUG_RDOC
1607
- break
1608
- end
1779
+ ##
1780
+ # Parses up to +no+ symbol arguments surrounded by () and places them in
1781
+ # +args+.
1782
+
1783
+ def parse_symbol_arg_paren no # :nodoc:
1784
+ args = []
1785
+
1786
+ loop do
1787
+ skip_tkspace_comment
1788
+ if tk1 = parse_symbol_in_arg
1789
+ args.push tk1
1790
+ break if no and args.size >= no
1609
1791
  end
1610
- else
1611
- unget_tk tk
1612
- if tk = parse_symbol_in_arg
1613
- args.push tk
1614
- return args if no and args.size >= no
1792
+
1793
+ skip_tkspace_comment
1794
+ case tk2 = get_tk
1795
+ when TkRPAREN
1796
+ break
1797
+ when TkCOMMA
1798
+ else
1799
+ warn("unexpected token: '#{tk2.inspect}'") if $DEBUG_RDOC
1800
+ break
1615
1801
  end
1802
+ end
1616
1803
 
1617
- loop do
1618
- skip_tkspace false
1804
+ args
1805
+ end
1619
1806
 
1620
- tk1 = get_tk
1621
- unless TkCOMMA === tk1 then
1622
- unget_tk tk1
1623
- break
1624
- end
1807
+ ##
1808
+ # Parses up to +no+ symbol arguments separated by spaces and places them in
1809
+ # +args+.
1625
1810
 
1626
- skip_tkspace_comment
1627
- if tk = parse_symbol_in_arg
1628
- args.push tk
1629
- break if no and args.size >= no
1630
- end
1811
+ def parse_symbol_arg_space no, tk # :nodoc:
1812
+ args = []
1813
+
1814
+ unget_tk tk
1815
+ if tk = parse_symbol_in_arg
1816
+ args.push tk
1817
+ return args if no and args.size >= no
1818
+ end
1819
+
1820
+ loop do
1821
+ skip_tkspace false
1822
+
1823
+ tk1 = get_tk
1824
+ unless TkCOMMA === tk1 then
1825
+ unget_tk tk1
1826
+ break
1827
+ end
1828
+
1829
+ skip_tkspace_comment
1830
+ if tk = parse_symbol_in_arg
1831
+ args.push tk
1832
+ break if no and args.size >= no
1631
1833
  end
1632
1834
  end
1633
1835
 
@@ -1659,6 +1861,8 @@ class RDoc::Parser::Ruby < RDoc::Parser
1659
1861
 
1660
1862
  look_for_directives_in container, comment
1661
1863
 
1864
+ throw :eof if container.done_documenting
1865
+
1662
1866
  @markup = comment.format
1663
1867
 
1664
1868
  # HACK move if to RDoc::Context#comment=
@@ -1673,24 +1877,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
1673
1877
  def parse_visibility(container, single, tk)
1674
1878
  singleton = (single == SINGLE)
1675
1879
 
1676
- vis_type = tk.name
1677
-
1678
- vis = case vis_type
1679
- when 'private' then :private
1680
- when 'protected' then :protected
1681
- when 'public' then :public
1682
- when 'private_class_method' then
1683
- singleton = true
1684
- :private
1685
- when 'public_class_method' then
1686
- singleton = true
1687
- :public
1688
- when 'module_function' then
1689
- singleton = true
1690
- :public
1691
- else
1692
- raise RDoc::Error, "Invalid visibility: #{tk.name}"
1693
- end
1880
+ vis_type, vis, singleton = get_visibility_information tk
1694
1881
 
1695
1882
  skip_tkspace_comment false
1696
1883
 
@@ -1703,45 +1890,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
1703
1890
  when TkNL, TkUNLESS_MOD, TkIF_MOD, TkSEMICOLON then
1704
1891
  container.ongoing_visibility = vis
1705
1892
  else
1706
- new_methods = []
1707
-
1708
- case vis_type
1709
- when 'module_function' then
1710
- args = parse_symbol_arg
1711
- container.set_visibility_for args, :private, false
1712
-
1713
- container.methods_matching args do |m|
1714
- s_m = m.dup
1715
- s_m.record_location @top_level
1716
- s_m.singleton = true
1717
- new_methods << s_m
1718
- end
1719
- when 'public_class_method', 'private_class_method' then
1720
- args = parse_symbol_arg
1721
-
1722
- container.methods_matching args, true do |m|
1723
- if m.parent != container then
1724
- m = m.dup
1725
- m.record_location @top_level
1726
- new_methods << m
1727
- end
1728
-
1729
- m.visibility = vis
1730
- end
1731
- else
1732
- args = parse_symbol_arg
1733
- container.set_visibility_for args, vis, singleton
1734
- end
1735
-
1736
- new_methods.each do |method|
1737
- case method
1738
- when RDoc::AnyMethod then
1739
- container.add_method method
1740
- when RDoc::Attr then
1741
- container.add_attribute method
1742
- end
1743
- method.visibility = vis
1744
- end
1893
+ update_visibility container, vis_type, vis, singleton
1745
1894
  end
1746
1895
  end
1747
1896
 
@@ -1752,7 +1901,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
1752
1901
  return if method.block_params
1753
1902
 
1754
1903
  get_tkread
1755
- @scanner.instance_eval { @continue = false }
1904
+ @scanner.continue = false
1756
1905
  method.block_params = parse_method_or_yield_parameters
1757
1906
  end
1758
1907
 
@@ -1777,7 +1926,8 @@ class RDoc::Parser::Ruby < RDoc::Parser
1777
1926
  tokens << tk
1778
1927
 
1779
1928
  case tk
1780
- when TkNL then return
1929
+ when TkNL, TkDEF then
1930
+ return
1781
1931
  when TkCOMMENT then
1782
1932
  return unless tk.text =~ /\s*:?([\w-]+):\s*(.*)/
1783
1933
 
@@ -1816,6 +1966,19 @@ class RDoc::Parser::Ruby < RDoc::Parser
1816
1966
  end
1817
1967
  end
1818
1968
 
1969
+ ##
1970
+ # Records the location of this +container+ in the file for this parser and
1971
+ # adds it to the list of classes and modules in the file.
1972
+
1973
+ def record_location container # :nodoc:
1974
+ case container
1975
+ when RDoc::ClassModule then
1976
+ @top_level.add_to_classes_or_modules container
1977
+ end
1978
+
1979
+ container.record_location @top_level
1980
+ end
1981
+
1819
1982
  ##
1820
1983
  # Removes private comments from +comment+
1821
1984
  #--
@@ -1826,7 +1989,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
1826
1989
  end
1827
1990
 
1828
1991
  ##
1829
- # Scans this ruby file for ruby constructs
1992
+ # Scans this Ruby file for Ruby constructs
1830
1993
 
1831
1994
  def scan
1832
1995
  reset
@@ -1874,16 +2037,11 @@ class RDoc::Parser::Ruby < RDoc::Parser
1874
2037
  def skip_optional_do_after_expression
1875
2038
  skip_tkspace false
1876
2039
  tk = get_tk
1877
- case tk
1878
- when TkLPAREN, TkfLPAREN then
1879
- end_token = TkRPAREN
1880
- else
1881
- end_token = TkNL
1882
- end
2040
+ end_token = get_end_token tk
1883
2041
 
1884
2042
  b_nest = 0
1885
2043
  nest = 0
1886
- @scanner.instance_eval { @continue = false }
2044
+ @scanner.continue = false
1887
2045
 
1888
2046
  loop do
1889
2047
  case tk
@@ -1900,7 +2058,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
1900
2058
  when end_token then
1901
2059
  if end_token == TkRPAREN
1902
2060
  nest -= 1
1903
- break if @scanner.lex_state == EXPR_END and nest.zero?
2061
+ break if @scanner.lex_state == :EXPR_END and nest.zero?
1904
2062
  else
1905
2063
  break unless @scanner.continue
1906
2064
  end
@@ -1946,6 +2104,51 @@ class RDoc::Parser::Ruby < RDoc::Parser
1946
2104
  end
1947
2105
  end
1948
2106
 
2107
+ ##
2108
+ # Updates visibility in +container+ from +vis_type+ and +vis+.
2109
+
2110
+ def update_visibility container, vis_type, vis, singleton # :nodoc:
2111
+ new_methods = []
2112
+
2113
+ case vis_type
2114
+ when 'module_function' then
2115
+ args = parse_symbol_arg
2116
+ container.set_visibility_for args, :private, false
2117
+
2118
+ container.methods_matching args do |m|
2119
+ s_m = m.dup
2120
+ record_location s_m
2121
+ s_m.singleton = true
2122
+ new_methods << s_m
2123
+ end
2124
+ when 'public_class_method', 'private_class_method' then
2125
+ args = parse_symbol_arg
2126
+
2127
+ container.methods_matching args, true do |m|
2128
+ if m.parent != container then
2129
+ m = m.dup
2130
+ record_location m
2131
+ new_methods << m
2132
+ end
2133
+
2134
+ m.visibility = vis
2135
+ end
2136
+ else
2137
+ args = parse_symbol_arg
2138
+ container.set_visibility_for args, vis, singleton
2139
+ end
2140
+
2141
+ new_methods.each do |method|
2142
+ case method
2143
+ when RDoc::AnyMethod then
2144
+ container.add_method method
2145
+ when RDoc::Attr then
2146
+ container.add_attribute method
2147
+ end
2148
+ method.visibility = vis
2149
+ end
2150
+ end
2151
+
1949
2152
  ##
1950
2153
  # Prints +message+ to +$stderr+ unless we're being quiet
1951
2154