rdoc 5.1.0 → 6.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. checksums.yaml +5 -5
  2. data/CONTRIBUTING.rdoc +5 -6
  3. data/ExampleMarkdown.md +2 -0
  4. data/ExampleRDoc.rdoc +2 -0
  5. data/History.rdoc +68 -66
  6. data/LEGAL.rdoc +1 -1
  7. data/LICENSE.rdoc +2 -0
  8. data/README.rdoc +18 -6
  9. data/RI.md +842 -0
  10. data/TODO.rdoc +8 -7
  11. data/exe/rdoc +0 -1
  12. data/lib/rdoc/{alias.rb → code_object/alias.rb} +4 -12
  13. data/lib/rdoc/{anon_class.rb → code_object/anon_class.rb} +1 -2
  14. data/lib/rdoc/{any_method.rb → code_object/any_method.rb} +83 -26
  15. data/lib/rdoc/{attr.rb → code_object/attr.rb} +5 -9
  16. data/lib/rdoc/{class_module.rb → code_object/class_module.rb} +112 -24
  17. data/lib/rdoc/{constant.rb → code_object/constant.rb} +4 -5
  18. data/lib/rdoc/{context → code_object/context}/section.rb +13 -83
  19. data/lib/rdoc/{context.rb → code_object/context.rb} +69 -70
  20. data/lib/rdoc/{extend.rb → code_object/extend.rb} +1 -2
  21. data/lib/rdoc/{ghost_method.rb → code_object/ghost_method.rb} +1 -2
  22. data/lib/rdoc/{include.rb → code_object/include.rb} +1 -2
  23. data/lib/rdoc/{meta_method.rb → code_object/meta_method.rb} +1 -2
  24. data/lib/rdoc/{method_attr.rb → code_object/method_attr.rb} +22 -31
  25. data/lib/rdoc/{mixin.rb → code_object/mixin.rb} +1 -2
  26. data/lib/rdoc/{normal_class.rb → code_object/normal_class.rb} +4 -5
  27. data/lib/rdoc/{normal_module.rb → code_object/normal_module.rb} +2 -3
  28. data/lib/rdoc/{require.rb → code_object/require.rb} +2 -3
  29. data/lib/rdoc/{single_class.rb → code_object/single_class.rb} +6 -2
  30. data/lib/rdoc/{top_level.rb → code_object/top_level.rb} +22 -32
  31. data/lib/rdoc/code_object.rb +8 -41
  32. data/lib/rdoc/code_objects.rb +2 -3
  33. data/lib/rdoc/comment.rb +48 -41
  34. data/lib/rdoc/cross_reference.rb +77 -33
  35. data/lib/rdoc/encoding.rb +50 -38
  36. data/lib/rdoc/erb_partial.rb +2 -3
  37. data/lib/rdoc/erbio.rb +4 -5
  38. data/lib/rdoc/generator/darkfish.rb +178 -125
  39. data/lib/rdoc/generator/json_index.rb +9 -22
  40. data/lib/rdoc/generator/markup.rb +6 -17
  41. data/lib/rdoc/generator/pot/message_extractor.rb +4 -4
  42. data/lib/rdoc/generator/pot/po.rb +3 -3
  43. data/lib/rdoc/generator/pot/po_entry.rb +12 -12
  44. data/lib/rdoc/generator/pot.rb +4 -8
  45. data/lib/rdoc/generator/ri.rb +1 -2
  46. data/lib/rdoc/generator/template/darkfish/_footer.rhtml +2 -2
  47. data/lib/rdoc/generator/template/darkfish/_head.rhtml +35 -12
  48. data/lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml +1 -5
  49. data/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml +7 -7
  50. data/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml +7 -7
  51. data/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml +6 -6
  52. data/lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml +19 -10
  53. data/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml +26 -6
  54. data/lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml +4 -9
  55. data/lib/rdoc/generator/template/darkfish/_sidebar_search.rhtml +1 -1
  56. data/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml +4 -4
  57. data/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml +27 -6
  58. data/lib/rdoc/generator/template/darkfish/_sidebar_toggle.rhtml +3 -0
  59. data/lib/rdoc/generator/template/darkfish/class.rhtml +125 -78
  60. data/lib/rdoc/generator/template/darkfish/css/rdoc.css +430 -339
  61. data/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttf +0 -0
  62. data/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttf +0 -0
  63. data/lib/rdoc/generator/template/darkfish/index.rhtml +13 -13
  64. data/lib/rdoc/generator/template/darkfish/js/darkfish.js +51 -92
  65. data/lib/rdoc/generator/template/darkfish/js/search.js +35 -34
  66. data/lib/rdoc/generator/template/darkfish/page.rhtml +5 -5
  67. data/lib/rdoc/generator/template/darkfish/servlet_not_found.rhtml +10 -8
  68. data/lib/rdoc/generator/template/darkfish/servlet_root.rhtml +20 -18
  69. data/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml +32 -20
  70. data/lib/rdoc/generator/template/json_index/js/navigation.js +12 -49
  71. data/lib/rdoc/generator/template/json_index/js/searcher.js +6 -6
  72. data/lib/rdoc/generator.rb +6 -6
  73. data/lib/rdoc/i18n/locale.rb +1 -1
  74. data/lib/rdoc/i18n/text.rb +5 -5
  75. data/lib/rdoc/i18n.rb +4 -4
  76. data/lib/rdoc/known_classes.rb +6 -5
  77. data/lib/rdoc/markdown/entities.rb +1 -2
  78. data/lib/rdoc/markdown/literals.kpeg +1 -2
  79. data/lib/rdoc/markdown/literals.rb +99 -50
  80. data/lib/rdoc/markdown.kpeg +115 -58
  81. data/lib/rdoc/markdown.rb +1584 -902
  82. data/lib/rdoc/markup/attr_changer.rb +1 -2
  83. data/lib/rdoc/markup/attr_span.rb +9 -4
  84. data/lib/rdoc/markup/attribute_manager.rb +118 -57
  85. data/lib/rdoc/markup/attributes.rb +7 -8
  86. data/lib/rdoc/markup/blank_line.rb +1 -2
  87. data/lib/rdoc/markup/block_quote.rb +1 -2
  88. data/lib/rdoc/markup/document.rb +1 -2
  89. data/lib/rdoc/markup/formatter.rb +44 -37
  90. data/lib/rdoc/markup/hard_break.rb +1 -2
  91. data/lib/rdoc/markup/heading.rb +11 -6
  92. data/lib/rdoc/markup/include.rb +1 -2
  93. data/lib/rdoc/markup/indented_paragraph.rb +1 -2
  94. data/lib/rdoc/markup/list.rb +1 -2
  95. data/lib/rdoc/markup/list_item.rb +1 -2
  96. data/lib/rdoc/markup/paragraph.rb +1 -2
  97. data/lib/rdoc/markup/parser.rb +90 -48
  98. data/lib/rdoc/markup/pre_process.rb +38 -11
  99. data/lib/rdoc/markup/raw.rb +1 -2
  100. data/lib/rdoc/markup/regexp_handling.rb +40 -0
  101. data/lib/rdoc/markup/rule.rb +1 -2
  102. data/lib/rdoc/markup/table.rb +56 -0
  103. data/lib/rdoc/markup/to_ansi.rb +1 -2
  104. data/lib/rdoc/markup/to_bs.rb +30 -5
  105. data/lib/rdoc/markup/to_html.rb +95 -40
  106. data/lib/rdoc/markup/to_html_crossref.rb +108 -43
  107. data/lib/rdoc/markup/to_html_snippet.rb +13 -11
  108. data/lib/rdoc/markup/to_joined_paragraph.rb +6 -32
  109. data/lib/rdoc/markup/to_label.rb +11 -12
  110. data/lib/rdoc/markup/to_markdown.rb +13 -14
  111. data/lib/rdoc/markup/to_rdoc.rb +49 -31
  112. data/lib/rdoc/markup/to_table_of_contents.rb +2 -2
  113. data/lib/rdoc/markup/to_test.rb +1 -2
  114. data/lib/rdoc/markup/to_tt_only.rb +3 -4
  115. data/lib/rdoc/markup/verbatim.rb +1 -2
  116. data/lib/rdoc/markup.rb +64 -694
  117. data/lib/rdoc/options.rb +226 -44
  118. data/lib/rdoc/parser/c.rb +231 -246
  119. data/lib/rdoc/parser/changelog.rb +169 -23
  120. data/lib/rdoc/parser/markdown.rb +1 -3
  121. data/lib/rdoc/parser/prism_ruby.rb +1092 -0
  122. data/lib/rdoc/parser/rd.rb +1 -2
  123. data/lib/rdoc/parser/ripper_state_lex.rb +302 -0
  124. data/lib/rdoc/parser/ruby.rb +695 -478
  125. data/lib/rdoc/parser/ruby_tools.rb +33 -36
  126. data/lib/rdoc/parser/simple.rb +4 -4
  127. data/lib/rdoc/parser/text.rb +1 -2
  128. data/lib/rdoc/parser.rb +37 -42
  129. data/lib/rdoc/rd/block_parser.rb +708 -57
  130. data/lib/rdoc/rd/block_parser.ry +15 -11
  131. data/lib/rdoc/rd/inline.rb +5 -6
  132. data/lib/rdoc/rd/inline_parser.rb +787 -140
  133. data/lib/rdoc/rd/inline_parser.ry +1 -1
  134. data/lib/rdoc/rd.rb +4 -5
  135. data/lib/rdoc/rdoc.rb +72 -87
  136. data/lib/rdoc/ri/driver.rb +236 -152
  137. data/lib/rdoc/ri/formatter.rb +1 -1
  138. data/lib/rdoc/ri/paths.rb +4 -18
  139. data/lib/rdoc/ri/store.rb +1 -2
  140. data/lib/rdoc/ri/task.rb +2 -2
  141. data/lib/rdoc/ri.rb +5 -6
  142. data/lib/rdoc/rubygems_hook.rb +98 -20
  143. data/lib/rdoc/servlet.rb +30 -20
  144. data/lib/rdoc/stats/normal.rb +24 -18
  145. data/lib/rdoc/stats/quiet.rb +1 -2
  146. data/lib/rdoc/stats/verbose.rb +1 -3
  147. data/lib/rdoc/stats.rb +6 -7
  148. data/lib/rdoc/store.rb +84 -55
  149. data/lib/rdoc/task.rb +35 -10
  150. data/lib/rdoc/text.rb +40 -27
  151. data/lib/rdoc/token_stream.rb +56 -34
  152. data/lib/rdoc/tom_doc.rb +18 -19
  153. data/lib/rdoc/version.rb +10 -0
  154. data/lib/rdoc.rb +80 -56
  155. data/lib/rubygems_plugin.rb +23 -0
  156. data/man/ri.1 +247 -0
  157. metadata +45 -99
  158. data/.document +0 -5
  159. data/.gitignore +0 -13
  160. data/.travis.yml +0 -24
  161. data/Gemfile +0 -3
  162. data/RI.rdoc +0 -57
  163. data/Rakefile +0 -133
  164. data/bin/console +0 -7
  165. data/bin/setup +0 -6
  166. data/lib/gauntlet_rdoc.rb +0 -82
  167. data/lib/rdoc/generator/template/darkfish/.document +0 -0
  168. data/lib/rdoc/generator/template/darkfish/_sidebar_VCS_info.rhtml +0 -19
  169. data/lib/rdoc/generator/template/darkfish/_sidebar_in_files.rhtml +0 -9
  170. data/lib/rdoc/generator/template/darkfish/js/jquery.js +0 -4
  171. data/lib/rdoc/generator/template/json_index/.document +0 -1
  172. data/lib/rdoc/markup/formatter_test_case.rb +0 -764
  173. data/lib/rdoc/markup/inline.rb +0 -2
  174. data/lib/rdoc/markup/special.rb +0 -41
  175. data/lib/rdoc/markup/text_formatter_test_case.rb +0 -115
  176. data/lib/rdoc/ruby_lex.rb +0 -1367
  177. data/lib/rdoc/ruby_token.rb +0 -461
  178. data/lib/rdoc/test_case.rb +0 -204
  179. data/rdoc.gemspec +0 -57
@@ -1,4 +1,4 @@
1
- # frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
  ##
3
3
  # This file contains stuff stolen outright from:
4
4
  #
@@ -8,7 +8,17 @@
8
8
  # by Keiju ISHITSUKA (Nippon Rational Inc.)
9
9
  #
10
10
 
11
- $TOKEN_DEBUG ||= nil
11
+ if ENV['RDOC_USE_PRISM_PARSER']
12
+ require 'rdoc/parser/prism_ruby'
13
+ RDoc::Parser.const_set(:Ruby, RDoc::Parser::PrismRuby)
14
+ puts "========================================================================="
15
+ puts "RDoc is using the experimental Prism parser to generate the documentation"
16
+ puts "========================================================================="
17
+ return
18
+ end
19
+
20
+ require 'ripper'
21
+ require_relative 'ripper_state_lex'
12
22
 
13
23
  ##
14
24
  # Extracts code elements from a source file returning a TopLevel object
@@ -24,6 +34,7 @@ $TOKEN_DEBUG ||= nil
24
34
  # * aliases
25
35
  # * private, public, protected
26
36
  # * private_class_function, public_class_function
37
+ # * private_constant, public_constant
27
38
  # * module_function
28
39
  # * attr, attr_reader, attr_writer, attr_accessor
29
40
  # * extra accessors given on the command line
@@ -143,7 +154,6 @@ class RDoc::Parser::Ruby < RDoc::Parser
143
154
 
144
155
  parse_files_matching(/\.rbw?$/)
145
156
 
146
- include RDoc::RubyToken
147
157
  include RDoc::TokenStream
148
158
  include RDoc::Parser::RubyTools
149
159
 
@@ -160,13 +170,17 @@ class RDoc::Parser::Ruby < RDoc::Parser
160
170
  ##
161
171
  # Creates a new Ruby parser.
162
172
 
163
- def initialize(top_level, file_name, content, options, stats)
173
+ def initialize(top_level, content, options, stats)
164
174
  super
165
175
 
176
+ content = handle_tab_width(content)
177
+
166
178
  @size = 0
167
179
  @token_listeners = nil
168
- @scanner = RDoc::RubyLex.new content, @options
169
- @scanner.exception_on_syntax_error = false
180
+ content = RDoc::Encoding.remove_magic_comment content
181
+ @scanner = RDoc::Parser::RipperStateLex.parse(content)
182
+ @content = content
183
+ @scanner_point = 0
170
184
  @prev_seek = nil
171
185
  @markup = @options.markup
172
186
  @track_visibility = :nodoc != @options.visibility
@@ -175,6 +189,13 @@ class RDoc::Parser::Ruby < RDoc::Parser
175
189
  reset
176
190
  end
177
191
 
192
+ ##
193
+ # Return +true+ if +tk+ is a newline.
194
+
195
+ def tk_nl?(tk)
196
+ :on_nl == tk[:kind] or :on_ignored_nl == tk[:kind]
197
+ end
198
+
178
199
  ##
179
200
  # Retrieves the read token stream and replaces +pattern+ with +replacement+
180
201
  # using gsub. If the result is only a ";" returns an empty string.
@@ -194,7 +215,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
194
215
  # methods.
195
216
 
196
217
  def get_visibility_information tk, single # :nodoc:
197
- vis_type = tk.name
218
+ vis_type = tk[:text]
198
219
  singleton = single == SINGLE
199
220
 
200
221
  vis =
@@ -223,31 +244,34 @@ class RDoc::Parser::Ruby < RDoc::Parser
223
244
 
224
245
  def collect_first_comment
225
246
  skip_tkspace
226
- comment = ''
227
- comment.force_encoding @encoding if @encoding
247
+ comment = ''.dup
248
+ comment = RDoc::Encoding.change_encoding comment, @encoding if @encoding
228
249
  first_line = true
229
- first_comment_tk_class = nil
250
+ first_comment_tk_kind = nil
251
+ line_no = nil
230
252
 
231
253
  tk = get_tk
232
254
 
233
- while TkCOMMENT === tk
234
- if first_line and tk.text =~ /\A#!/ then
255
+ while tk && (:on_comment == tk[:kind] or :on_embdoc == tk[:kind])
256
+ comment_body = retrieve_comment_body(tk)
257
+ if first_line and comment_body =~ /\A#!/ then
235
258
  skip_tkspace
236
259
  tk = get_tk
237
- elsif first_line and tk.text =~ /\A#\s*-\*-/ then
260
+ elsif first_line and comment_body =~ /\A#\s*-\*-/ then
238
261
  first_line = false
239
262
  skip_tkspace
240
263
  tk = get_tk
241
264
  else
242
- break if first_comment_tk_class and not first_comment_tk_class === tk
243
- first_comment_tk_class = tk.class
265
+ break if first_comment_tk_kind and not first_comment_tk_kind === tk[:kind]
266
+ first_comment_tk_kind = tk[:kind]
244
267
 
268
+ line_no = tk[:line_no] if first_line
245
269
  first_line = false
246
- comment << tk.text << "\n"
270
+ comment << comment_body
247
271
  tk = get_tk
248
272
 
249
- if TkNL === tk then
250
- skip_tkspace false
273
+ if :on_nl === tk then
274
+ skip_tkspace_without_nl
251
275
  tk = get_tk
252
276
  end
253
277
  end
@@ -255,22 +279,21 @@ class RDoc::Parser::Ruby < RDoc::Parser
255
279
 
256
280
  unget_tk tk
257
281
 
258
- new_comment comment
282
+ new_comment comment, line_no
259
283
  end
260
284
 
261
285
  ##
262
286
  # Consumes trailing whitespace from the token stream
263
287
 
264
288
  def consume_trailing_spaces # :nodoc:
265
- get_tkread
266
- skip_tkspace false
289
+ skip_tkspace_without_nl
267
290
  end
268
291
 
269
292
  ##
270
293
  # Creates a new attribute in +container+ with +name+.
271
294
 
272
295
  def create_attr container, single, name, rw, comment # :nodoc:
273
- att = RDoc::Attr.new get_tkread, name, rw, comment, single == SINGLE
296
+ att = RDoc::Attr.new get_tkread, name, rw, comment, singleton: single == SINGLE
274
297
  record_location att
275
298
 
276
299
  container.add_attribute att
@@ -290,7 +313,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
290
313
  container.find_module_named rhs_name
291
314
  end
292
315
 
293
- container.add_module_alias mod, constant.name, @top_level if mod
316
+ container.add_module_alias mod, rhs_name, constant, @top_level
294
317
  end
295
318
 
296
319
  ##
@@ -303,16 +326,14 @@ class RDoc::Parser::Ruby < RDoc::Parser
303
326
  end
304
327
 
305
328
  ##
306
- # Looks for a true or false token. Returns false if TkFALSE or TkNIL are
307
- # found.
329
+ # Looks for a true or false token.
308
330
 
309
331
  def get_bool
310
332
  skip_tkspace
311
333
  tk = get_tk
312
- case tk
313
- when TkTRUE
334
+ if :on_kw == tk[:kind] && 'true' == tk[:text]
314
335
  true
315
- when TkFALSE, TkNIL
336
+ elsif :on_kw == tk[:kind] && ('false' == tk[:text] || 'nil' == tk[:text])
316
337
  false
317
338
  else
318
339
  unget_tk tk
@@ -328,27 +349,31 @@ class RDoc::Parser::Ruby < RDoc::Parser
328
349
  def get_class_or_module container, ignore_constants = false
329
350
  skip_tkspace
330
351
  name_t = get_tk
331
- given_name = ''
352
+ given_name = ''.dup
332
353
 
333
354
  # class ::A -> A is in the top level
334
- case name_t
335
- when TkCOLON2, TkCOLON3 then # bug
355
+ if :on_op == name_t[:kind] and '::' == name_t[:text] then # bug
336
356
  name_t = get_tk
337
357
  container = @top_level
338
358
  given_name << '::'
339
359
  end
340
360
 
341
- skip_tkspace false
342
- given_name << name_t.name
361
+ skip_tkspace_without_nl
362
+ given_name << name_t[:text]
343
363
 
344
- while TkCOLON2 === peek_tk do
364
+ is_self = name_t[:kind] == :on_op && name_t[:text] == '<<'
365
+ new_modules = []
366
+ while !is_self && (tk = peek_tk) and :on_op == tk[:kind] and '::' == tk[:text] do
345
367
  prev_container = container
346
- container = container.find_module_named name_t.name
368
+ container = container.find_module_named name_t[:text]
347
369
  container ||=
348
370
  if ignore_constants then
349
- RDoc::Context.new
371
+ c = RDoc::NormalModule.new name_t[:text]
372
+ c.store = @store
373
+ new_modules << [prev_container, c]
374
+ c
350
375
  else
351
- c = prev_container.add_module RDoc::NormalModule, name_t.name
376
+ c = prev_container.add_module RDoc::NormalModule, name_t[:text]
352
377
  c.ignore unless prev_container.document_children
353
378
  @top_level.add_to_classes_or_modules c
354
379
  c
@@ -357,35 +382,74 @@ class RDoc::Parser::Ruby < RDoc::Parser
357
382
  record_location container
358
383
 
359
384
  get_tk
360
- skip_tkspace false
385
+ skip_tkspace
386
+ if :on_lparen == peek_tk[:kind] # ProcObjectInConstant::()
387
+ parse_method_or_yield_parameters
388
+ break
389
+ end
361
390
  name_t = get_tk
362
- given_name << '::' << name_t.name
391
+ unless :on_const == name_t[:kind] || :on_ident == name_t[:kind]
392
+ raise RDoc::Error, "Invalid class or module definition: #{given_name}"
393
+ end
394
+ if prev_container == container and !ignore_constants
395
+ given_name = name_t[:text]
396
+ else
397
+ given_name << '::' + name_t[:text]
398
+ end
363
399
  end
364
400
 
365
- skip_tkspace false
401
+ skip_tkspace_without_nl
366
402
 
367
- return [container, name_t, given_name]
403
+ return [container, name_t, given_name, new_modules]
404
+ end
405
+
406
+ ##
407
+ # Skip opening parentheses and yield the block.
408
+ # Skip closing parentheses too when exists.
409
+
410
+ def skip_parentheses(&block)
411
+ left_tk = peek_tk
412
+
413
+ if :on_lparen == left_tk[:kind]
414
+ get_tk
415
+
416
+ ret = skip_parentheses(&block)
417
+
418
+ right_tk = peek_tk
419
+ if :on_rparen == right_tk[:kind]
420
+ get_tk
421
+ end
422
+
423
+ ret
424
+ else
425
+ yield
426
+ end
368
427
  end
369
428
 
370
429
  ##
371
430
  # Return a superclass, which can be either a constant of an expression
372
431
 
373
432
  def get_class_specification
374
- case peek_tk
375
- when TkSELF then return 'self'
376
- when TkGVAR then return ''
433
+ tk = peek_tk
434
+ if tk.nil?
435
+ return ''
436
+ elsif :on_kw == tk[:kind] && 'self' == tk[:text]
437
+ return 'self'
438
+ elsif :on_gvar == tk[:kind]
439
+ return ''
377
440
  end
378
441
 
379
442
  res = get_constant
380
443
 
381
- skip_tkspace false
444
+ skip_tkspace_without_nl
382
445
 
383
446
  get_tkread # empty out read buffer
384
447
 
385
448
  tk = get_tk
449
+ return res unless tk
386
450
 
387
- case tk
388
- when TkNL, TkCOMMENT, TkSEMICOLON then
451
+ case tk[:kind]
452
+ when :on_nl, :on_comment, :on_embdoc, :on_semicolon then
389
453
  unget_tk(tk)
390
454
  return res
391
455
  end
@@ -400,11 +464,11 @@ class RDoc::Parser::Ruby < RDoc::Parser
400
464
 
401
465
  def get_constant
402
466
  res = ""
403
- skip_tkspace false
467
+ skip_tkspace_without_nl
404
468
  tk = get_tk
405
469
 
406
- while TkCOLON2 === tk or TkCOLON3 === tk or TkCONSTANT === tk do
407
- res += tk.name
470
+ while tk && ((:on_op == tk[:kind] && '::' == tk[:text]) || :on_const == tk[:kind]) do
471
+ res += tk[:text]
408
472
  tk = get_tk
409
473
  end
410
474
 
@@ -413,28 +477,83 @@ class RDoc::Parser::Ruby < RDoc::Parser
413
477
  end
414
478
 
415
479
  ##
416
- # Get a constant that may be surrounded by parens
480
+ # Get an included module that may be surrounded by parens
417
481
 
418
- def get_constant_with_optional_parens
419
- skip_tkspace false
482
+ def get_included_module_with_optional_parens
483
+ skip_tkspace_without_nl
484
+ get_tkread
485
+ tk = get_tk
486
+ end_token = get_end_token tk
487
+ return '' unless end_token
420
488
 
421
489
  nest = 0
490
+ continue = false
491
+ only_constant = true
422
492
 
423
- while TkLPAREN === (tk = peek_tk) or TkfLPAREN === tk do
424
- get_tk
425
- skip_tkspace
426
- nest += 1
427
- end
428
-
429
- name = get_constant
430
-
431
- while nest > 0
432
- skip_tkspace
493
+ while tk != nil do
494
+ is_element_of_constant = false
495
+ case tk[:kind]
496
+ when :on_semicolon then
497
+ break if nest == 0
498
+ when :on_lbracket then
499
+ nest += 1
500
+ when :on_rbracket then
501
+ nest -= 1
502
+ when :on_lbrace then
503
+ nest += 1
504
+ when :on_rbrace then
505
+ nest -= 1
506
+ if nest <= 0
507
+ # we might have a.each { |i| yield i }
508
+ unget_tk(tk) if nest < 0
509
+ break
510
+ end
511
+ when :on_lparen then
512
+ nest += 1
513
+ when end_token[:kind] then
514
+ if end_token[:kind] == :on_rparen
515
+ nest -= 1
516
+ break if nest <= 0
517
+ else
518
+ break if nest <= 0
519
+ end
520
+ when :on_rparen then
521
+ nest -= 1
522
+ when :on_comment, :on_embdoc then
523
+ @read.pop
524
+ if :on_nl == end_token[:kind] and "\n" == tk[:text][-1] and
525
+ (!continue or (tk[:state] & Ripper::EXPR_LABEL) != 0) then
526
+ break if !continue and nest <= 0
527
+ end
528
+ when :on_comma then
529
+ continue = true
530
+ when :on_ident then
531
+ continue = false if continue
532
+ when :on_kw then
533
+ case tk[:text]
534
+ when 'def', 'do', 'case', 'for', 'begin', 'class', 'module'
535
+ nest += 1
536
+ when 'if', 'unless', 'while', 'until', 'rescue'
537
+ # postfix if/unless/while/until/rescue must be EXPR_LABEL
538
+ nest += 1 unless (tk[:state] & Ripper::EXPR_LABEL) != 0
539
+ when 'end'
540
+ nest -= 1
541
+ break if nest == 0
542
+ end
543
+ when :on_const then
544
+ is_element_of_constant = true
545
+ when :on_op then
546
+ is_element_of_constant = true if '::' == tk[:text]
547
+ end
548
+ only_constant = false unless is_element_of_constant
433
549
  tk = get_tk
434
- nest -= 1 if TkRPAREN === tk
435
550
  end
436
551
 
437
- name
552
+ if only_constant
553
+ get_tkread_clean(/\s+/, ' ')
554
+ else
555
+ ''
556
+ end
438
557
  end
439
558
 
440
559
  ##
@@ -446,13 +565,19 @@ class RDoc::Parser::Ruby < RDoc::Parser
446
565
  # won't catch all cases (such as "a = yield + 1"
447
566
 
448
567
  def get_end_token tk # :nodoc:
449
- case tk
450
- when TkLPAREN, TkfLPAREN
451
- TkRPAREN
452
- when TkRPAREN
568
+ case tk[:kind]
569
+ when :on_lparen
570
+ token = RDoc::Parser::RipperStateLex::Token.new
571
+ token[:kind] = :on_rparen
572
+ token[:text] = ')'
573
+ token
574
+ when :on_rparen
453
575
  nil
454
576
  else
455
- TkNL
577
+ token = RDoc::Parser::RipperStateLex::Token.new
578
+ token[:kind] = :on_nl
579
+ token[:text] = "\n"
580
+ token
456
581
  end
457
582
  end
458
583
 
@@ -461,11 +586,11 @@ class RDoc::Parser::Ruby < RDoc::Parser
461
586
 
462
587
  def get_method_container container, name_t # :nodoc:
463
588
  prev_container = container
464
- container = container.find_module_named(name_t.name)
589
+ container = container.find_module_named(name_t[:text])
465
590
 
466
591
  unless container then
467
592
  constant = prev_container.constants.find do |const|
468
- const.name == name_t.name
593
+ const.name == name_t[:text]
469
594
  end
470
595
 
471
596
  if constant then
@@ -476,21 +601,21 @@ class RDoc::Parser::Ruby < RDoc::Parser
476
601
 
477
602
  unless container then
478
603
  # TODO seems broken, should starting at Object in @store
479
- obj = name_t.name.split("::").inject(Object) do |state, item|
604
+ obj = name_t[:text].split("::").inject(Object) do |state, item|
480
605
  state.const_get(item)
481
606
  end rescue nil
482
607
 
483
608
  type = obj.class == Class ? RDoc::NormalClass : RDoc::NormalModule
484
609
 
485
610
  unless [Class, Module].include?(obj.class) then
486
- warn("Couldn't find #{name_t.name}. Assuming it's a module")
611
+ warn("Couldn't find #{name_t[:text]}. Assuming it's a module")
487
612
  end
488
613
 
489
614
  if type == RDoc::NormalClass then
490
615
  sclass = obj.superclass ? obj.superclass.name : nil
491
- container = prev_container.add_class type, name_t.name, sclass
616
+ container = prev_container.add_class type, name_t[:text], sclass
492
617
  else
493
- container = prev_container.add_module type, name_t.name
618
+ container = prev_container.add_module type, name_t[:text]
494
619
  end
495
620
 
496
621
  record_location container
@@ -504,32 +629,26 @@ class RDoc::Parser::Ruby < RDoc::Parser
504
629
 
505
630
  def get_symbol_or_name
506
631
  tk = get_tk
507
- case tk
508
- when TkSYMBOL then
509
- text = tk.text.sub(/^:/, '')
632
+ case tk[:kind]
633
+ when :on_symbol then
634
+ text = tk[:text].sub(/^:/, '')
510
635
 
511
- if TkASSIGN === peek_tk then
636
+ next_tk = peek_tk
637
+ if next_tk && :on_op == next_tk[:kind] && '=' == next_tk[:text] then
512
638
  get_tk
513
639
  text << '='
514
640
  end
515
641
 
516
642
  text
517
- when TkId, TkOp then
518
- tk.name
519
- when TkAMPER,
520
- TkDSTRING,
521
- TkSTAR,
522
- TkSTRING then
523
- tk.text
643
+ when :on_ident, :on_const, :on_gvar, :on_cvar, :on_ivar, :on_op, :on_kw then
644
+ tk[:text]
645
+ when :on_tstring, :on_dstring then
646
+ tk[:text][1..-2]
524
647
  else
525
648
  raise RDoc::Error, "Name or symbol expected (got #{tk})"
526
649
  end
527
650
  end
528
651
 
529
- def stop_at_EXPR_END # :nodoc:
530
- @scanner.lex_state == :EXPR_END || !@scanner.continue
531
- end
532
-
533
652
  ##
534
653
  # Marks containers between +container+ and +ancestor+ as ignored
535
654
 
@@ -548,29 +667,31 @@ class RDoc::Parser::Ruby < RDoc::Parser
548
667
  #
549
668
  # This routine modifies its +comment+ parameter.
550
669
 
551
- def look_for_directives_in context, comment
552
- @preprocess.handle comment, context do |directive, param|
670
+ def look_for_directives_in container, comment
671
+ @preprocess.handle comment, container do |directive, param|
553
672
  case directive
554
673
  when 'method', 'singleton-method',
555
674
  'attr', 'attr_accessor', 'attr_reader', 'attr_writer' then
556
675
  false # handled elsewhere
557
676
  when 'section' then
558
- context.set_current_section param, comment.dup
677
+ break unless container.kind_of?(RDoc::Context)
678
+ container.set_current_section param, comment.dup
559
679
  comment.text = ''
560
680
  break
561
681
  end
562
682
  end
563
683
 
564
- remove_private_comments comment
684
+ comment.remove_private
565
685
  end
566
686
 
567
687
  ##
568
688
  # Adds useful info about the parser to +message+
569
689
 
570
690
  def make_message message
571
- prefix = "#{@file_name}:"
691
+ prefix = "#{@file_name}:".dup
572
692
 
573
- prefix << "#{@scanner.line_no}:#{@scanner.char_no}:" if @scanner
693
+ tk = peek_tk
694
+ prefix << "#{tk[:line_no]}:#{tk[:char_no]}:" if tk
574
695
 
575
696
  "#{prefix} #{message}"
576
697
  end
@@ -578,8 +699,9 @@ class RDoc::Parser::Ruby < RDoc::Parser
578
699
  ##
579
700
  # Creates a comment with the correct format
580
701
 
581
- def new_comment comment
582
- c = RDoc::Comment.new comment, @top_level
702
+ def new_comment comment, line_no = nil
703
+ c = RDoc::Comment.new comment, @top_level, :ruby
704
+ c.line = line_no
583
705
  c.format = @markup
584
706
  c
585
707
  end
@@ -589,24 +711,22 @@ class RDoc::Parser::Ruby < RDoc::Parser
589
711
  # +comment+.
590
712
 
591
713
  def parse_attr(context, single, tk, comment)
592
- offset = tk.seek
593
- line_no = tk.line_no
714
+ line_no = tk[:line_no]
594
715
 
595
716
  args = parse_symbol_arg 1
596
717
  if args.size > 0 then
597
718
  name = args[0]
598
719
  rw = "R"
599
- skip_tkspace false
720
+ skip_tkspace_without_nl
600
721
  tk = get_tk
601
722
 
602
- if TkCOMMA === tk then
723
+ if :on_comma == tk[:kind] then
603
724
  rw = "RW" if get_bool
604
725
  else
605
726
  unget_tk tk
606
727
  end
607
728
 
608
729
  att = create_attr context, single, name, rw, comment
609
- att.offset = offset
610
730
  att.line = line_no
611
731
 
612
732
  read_documentation_modifiers att, RDoc::ATTR_MODIFIERS
@@ -620,8 +740,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
620
740
  # comment for each to +comment+.
621
741
 
622
742
  def parse_attr_accessor(context, single, tk, comment)
623
- offset = tk.seek
624
- line_no = tk.line_no
743
+ line_no = tk[:line_no]
625
744
 
626
745
  args = parse_symbol_arg
627
746
  rw = "?"
@@ -632,7 +751,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
632
751
  # and add found items appropriately but here we do not. I'm not sure why.
633
752
  return if @track_visibility and not tmp.document_self
634
753
 
635
- case tk.name
754
+ case tk[:text]
636
755
  when "attr_reader" then rw = "R"
637
756
  when "attr_writer" then rw = "W"
638
757
  when "attr_accessor" then rw = "RW"
@@ -642,7 +761,6 @@ class RDoc::Parser::Ruby < RDoc::Parser
642
761
 
643
762
  for name in args
644
763
  att = create_attr context, single, name, rw, comment
645
- att.offset = offset
646
764
  att.line = line_no
647
765
  end
648
766
  end
@@ -651,22 +769,19 @@ class RDoc::Parser::Ruby < RDoc::Parser
651
769
  # Parses an +alias+ in +context+ with +comment+
652
770
 
653
771
  def parse_alias(context, single, tk, comment)
654
- offset = tk.seek
655
- line_no = tk.line_no
772
+ line_no = tk[:line_no]
656
773
 
657
774
  skip_tkspace
658
775
 
659
- if TkLPAREN === peek_tk then
776
+ if :on_lparen === peek_tk[:kind] then
660
777
  get_tk
661
778
  skip_tkspace
662
779
  end
663
780
 
664
781
  new_name = get_symbol_or_name
665
782
 
666
- @scanner.lex_state = :EXPR_FNAME
667
-
668
783
  skip_tkspace
669
- if TkCOMMA === peek_tk then
784
+ if :on_comma === peek_tk[:kind] then
670
785
  get_tk
671
786
  skip_tkspace
672
787
  end
@@ -677,15 +792,15 @@ class RDoc::Parser::Ruby < RDoc::Parser
677
792
  return
678
793
  end
679
794
 
680
- al = RDoc::Alias.new(get_tkread, old_name, new_name, comment,
681
- single == SINGLE)
795
+ al = RDoc::Alias.new(get_tkread, old_name, new_name, comment, singleton: single == SINGLE)
682
796
  record_location al
683
- al.offset = offset
684
797
  al.line = line_no
685
798
 
686
799
  read_documentation_modifiers al, RDoc::ATTR_MODIFIERS
687
- context.add_alias al
688
- @stats.add_alias al
800
+ if al.document_self or not @track_visibility
801
+ context.add_alias al
802
+ @stats.add_alias al
803
+ end
689
804
 
690
805
  al
691
806
  end
@@ -694,34 +809,38 @@ class RDoc::Parser::Ruby < RDoc::Parser
694
809
  # Extracts call parameters from the token stream.
695
810
 
696
811
  def parse_call_parameters(tk)
697
- end_token = case tk
698
- when TkLPAREN, TkfLPAREN
699
- TkRPAREN
700
- when TkRPAREN
812
+ end_token = case tk[:kind]
813
+ when :on_lparen
814
+ :on_rparen
815
+ when :on_rparen
701
816
  return ""
702
817
  else
703
- TkNL
818
+ :on_nl
704
819
  end
705
820
  nest = 0
706
821
 
707
822
  loop do
708
- case tk
709
- when TkSEMICOLON
823
+ break if tk.nil?
824
+ case tk[:kind]
825
+ when :on_semicolon
710
826
  break
711
- when TkLPAREN, TkfLPAREN
827
+ when :on_lparen
712
828
  nest += 1
713
829
  when end_token
714
- if end_token == TkRPAREN
830
+ if end_token == :on_rparen
715
831
  nest -= 1
716
- break if @scanner.lex_state == :EXPR_END and nest <= 0
832
+ break if RDoc::Parser::RipperStateLex.end?(tk) and nest <= 0
717
833
  else
718
- break unless @scanner.continue
834
+ break if RDoc::Parser::RipperStateLex.end?(tk)
719
835
  end
720
- when TkCOMMENT, TkASSIGN, TkOPASGN
836
+ when :on_comment, :on_embdoc
721
837
  unget_tk(tk)
722
838
  break
723
- when nil then
724
- break
839
+ when :on_op
840
+ if tk[:text] =~ /^(.{1,2})?=$/
841
+ unget_tk(tk)
842
+ break
843
+ end
725
844
  end
726
845
  tk = get_tk
727
846
  end
@@ -733,33 +852,33 @@ class RDoc::Parser::Ruby < RDoc::Parser
733
852
  # Parses a class in +context+ with +comment+
734
853
 
735
854
  def parse_class container, single, tk, comment
736
- offset = tk.seek
737
- line_no = tk.line_no
855
+ line_no = tk[:line_no]
738
856
 
739
857
  declaration_context = container
740
- container, name_t, given_name = get_class_or_module container
741
-
742
- cls =
743
- case name_t
744
- when TkCONSTANT
745
- parse_class_regular container, declaration_context, single,
746
- name_t, given_name, comment
747
- when TkLSHFT
748
- case name = get_class_specification
749
- when 'self', container.name
750
- parse_statements container, SINGLE
751
- return # don't update offset or line
752
- else
753
- parse_class_singleton container, name, comment
754
- end
858
+ container, name_t, given_name, = get_class_or_module container
859
+
860
+ if name_t[:kind] == :on_const
861
+ cls = parse_class_regular container, declaration_context, single,
862
+ name_t, given_name, comment
863
+ elsif name_t[:kind] == :on_op && name_t[:text] == '<<'
864
+ case name = skip_parentheses { get_class_specification }
865
+ when 'self', container.name
866
+ read_documentation_modifiers cls, RDoc::CLASS_MODIFIERS
867
+ parse_statements container, SINGLE
868
+ return # don't update line
755
869
  else
756
- warn "Expected class name or '<<'. Got #{name_t.class}: #{name_t.text.inspect}"
757
- return
870
+ cls = parse_class_singleton container, name, comment
758
871
  end
872
+ else
873
+ warn "Expected class name or '<<'. Got #{name_t[:kind]}: #{name_t[:text].inspect}"
874
+ return
875
+ end
759
876
 
760
- cls.offset = offset
761
877
  cls.line = line_no
762
878
 
879
+ # after end modifiers
880
+ read_documentation_modifiers cls, RDoc::CLASS_MODIFIERS
881
+
763
882
  cls
764
883
  end
765
884
 
@@ -775,7 +894,8 @@ class RDoc::Parser::Ruby < RDoc::Parser
775
894
  given_name = $'
776
895
  end
777
896
 
778
- if TkLT === peek_tk then
897
+ tk = peek_tk
898
+ if tk[:kind] == :on_op && tk[:text] == '<' then
779
899
  get_tk
780
900
  skip_tkspace
781
901
  superclass = get_class_specification
@@ -845,102 +965,125 @@ class RDoc::Parser::Ruby < RDoc::Parser
845
965
  # true, no found constants will be added to RDoc.
846
966
 
847
967
  def parse_constant container, tk, comment, ignore_constants = false
848
- offset = tk.seek
849
- line_no = tk.line_no
968
+ line_no = tk[:line_no]
850
969
 
851
- name = tk.name
852
- skip_tkspace false
970
+ name = tk[:text]
971
+ skip_tkspace_without_nl
853
972
 
854
973
  return unless name =~ /^\w+$/
855
974
 
856
- eq_tk = get_tk
857
-
858
- if TkCOLON2 === eq_tk then
859
- unget_tk eq_tk
975
+ new_modules = []
976
+ if :on_op == peek_tk[:kind] && '::' == peek_tk[:text] then
860
977
  unget_tk tk
861
978
 
862
- container, name_t, = get_class_or_module container, ignore_constants
979
+ container, name_t, _, new_modules = get_class_or_module container, true
863
980
 
864
- name = name_t.name
981
+ name = name_t[:text]
982
+ end
865
983
 
866
- eq_tk = get_tk
984
+ is_array_or_hash = false
985
+ if peek_tk && :on_lbracket == peek_tk[:kind]
986
+ get_tk
987
+ nest = 1
988
+ while bracket_tk = get_tk
989
+ case bracket_tk[:kind]
990
+ when :on_lbracket
991
+ nest += 1
992
+ when :on_rbracket
993
+ nest -= 1
994
+ break if nest == 0
995
+ end
996
+ end
997
+ skip_tkspace_without_nl
998
+ is_array_or_hash = true
867
999
  end
868
1000
 
869
- unless TkASSIGN === eq_tk then
870
- unget_tk eq_tk
1001
+ unless peek_tk && :on_op == peek_tk[:kind] && '=' == peek_tk[:text] then
871
1002
  return false
872
1003
  end
1004
+ get_tk
873
1005
 
874
- if TkGT === peek_tk then
875
- unget_tk eq_tk
876
- return
1006
+ unless ignore_constants
1007
+ new_modules.each do |prev_c, new_module|
1008
+ prev_c.add_module_by_normal_module new_module
1009
+ new_module.ignore unless prev_c.document_children
1010
+ @top_level.add_to_classes_or_modules new_module
1011
+ end
877
1012
  end
878
1013
 
879
1014
  value = ''
880
1015
  con = RDoc::Constant.new name, value, comment
881
1016
 
882
- body = parse_constant_body container, con
1017
+ body = parse_constant_body container, con, is_array_or_hash
883
1018
 
884
1019
  return unless body
885
1020
 
886
- value.replace body
1021
+ con.value = body
887
1022
  record_location con
888
- con.offset = offset
889
1023
  con.line = line_no
890
1024
  read_documentation_modifiers con, RDoc::CONSTANT_MODIFIERS
891
1025
 
1026
+ return if is_array_or_hash
1027
+
892
1028
  @stats.add_constant con
893
1029
  container.add_constant con
894
1030
 
895
1031
  true
896
1032
  end
897
1033
 
898
- def parse_constant_body container, constant # :nodoc:
1034
+ def parse_constant_body container, constant, is_array_or_hash # :nodoc:
899
1035
  nest = 0
900
- rhs_name = ''
1036
+ rhs_name = ''.dup
901
1037
 
902
1038
  get_tkread
903
1039
 
904
1040
  tk = get_tk
905
1041
 
1042
+ body = nil
906
1043
  loop do
907
- case tk
908
- when TkSEMICOLON then
1044
+ break if tk.nil?
1045
+ if :on_semicolon == tk[:kind] then
909
1046
  break if nest <= 0
910
- when TkLPAREN, TkfLPAREN, TkLBRACE, TkfLBRACE, TkLBRACK, TkfLBRACK,
911
- TkDO, TkIF, TkUNLESS, TkCASE, TkDEF, TkBEGIN then
1047
+ elsif [:on_tlambeg, :on_lparen, :on_lbrace, :on_lbracket].include?(tk[:kind]) then
1048
+ nest += 1
1049
+ elsif (:on_kw == tk[:kind] && 'def' == tk[:text]) then
912
1050
  nest += 1
913
- when TkRPAREN, TkRBRACE, TkRBRACK, TkEND then
1051
+ elsif (:on_kw == tk[:kind] && %w{do if unless case begin}.include?(tk[:text])) then
1052
+ if (tk[:state] & Ripper::EXPR_LABEL) == 0
1053
+ nest += 1
1054
+ end
1055
+ elsif [:on_rparen, :on_rbrace, :on_rbracket].include?(tk[:kind]) ||
1056
+ (:on_kw == tk[:kind] && 'end' == tk[:text]) then
914
1057
  nest -= 1
915
- when TkCOMMENT then
916
- if nest <= 0 and stop_at_EXPR_END then
917
- unget_tk tk
1058
+ elsif (:on_comment == tk[:kind] or :on_embdoc == tk[:kind]) then
1059
+ unget_tk tk
1060
+ if nest <= 0 and RDoc::Parser::RipperStateLex.end?(tk) then
1061
+ body = get_tkread_clean(/^[ \t]+/, '')
1062
+ read_documentation_modifiers constant, RDoc::CONSTANT_MODIFIERS
918
1063
  break
919
1064
  else
920
- unget_tk tk
921
1065
  read_documentation_modifiers constant, RDoc::CONSTANT_MODIFIERS
922
1066
  end
923
- when TkCONSTANT then
924
- rhs_name << tk.name
1067
+ elsif :on_const == tk[:kind] then
1068
+ rhs_name << tk[:text]
925
1069
 
926
- if nest <= 0 and TkNL === peek_tk then
927
- create_module_alias container, constant, rhs_name
1070
+ next_tk = peek_tk
1071
+ if nest <= 0 and (next_tk.nil? || :on_nl == next_tk[:kind]) then
1072
+ create_module_alias container, constant, rhs_name unless is_array_or_hash
928
1073
  break
929
1074
  end
930
- when TkNL then
931
- if nest <= 0 and stop_at_EXPR_END then
1075
+ elsif :on_nl == tk[:kind] then
1076
+ if nest <= 0 and RDoc::Parser::RipperStateLex.end?(tk) then
932
1077
  unget_tk tk
933
1078
  break
934
1079
  end
935
- when TkCOLON2, TkCOLON3 then
1080
+ elsif :on_op == tk[:kind] && '::' == tk[:text]
936
1081
  rhs_name << '::'
937
- when nil then
938
- break
939
1082
  end
940
1083
  tk = get_tk
941
1084
  end
942
1085
 
943
- get_tkread_clean(/^[ \t]+/, '')
1086
+ body ? body : get_tkread_clean(/^[ \t]+/, '')
944
1087
  end
945
1088
 
946
1089
  ##
@@ -949,24 +1092,22 @@ class RDoc::Parser::Ruby < RDoc::Parser
949
1092
 
950
1093
  def parse_comment container, tk, comment
951
1094
  return parse_comment_tomdoc container, tk, comment if @markup == 'tomdoc'
952
- column = tk.char_no
953
- offset = tk.seek
954
- line_no = tk.line_no
955
-
956
- text = comment.text
1095
+ column = tk[:char_no]
1096
+ line_no = comment.line.nil? ? tk[:line_no] : comment.line
957
1097
 
958
- singleton = !!text.sub!(/(^# +:?)(singleton-)(method:)/, '\1\3')
1098
+ comment.text = comment.text.sub(/(^# +:?)(singleton-)(method:)/, '\1\3')
1099
+ singleton = !!$~
959
1100
 
960
1101
  co =
961
- if text.sub!(/^# +:?method: *(\S*).*?\n/i, '') then
962
- parse_comment_ghost container, text, $1, column, line_no, comment
963
- elsif text.sub!(/# +:?(attr(_reader|_writer|_accessor)?): *(\S*).*?\n/i, '') then
1102
+ if (comment.text = comment.text.sub(/^# +:?method: *(\S*).*?\n/i, '')) && !!$~ then
1103
+ line_no += $`.count("\n")
1104
+ parse_comment_ghost container, comment.text, $1, column, line_no, comment
1105
+ elsif (comment.text = comment.text.sub(/# +:?(attr(_reader|_writer|_accessor)?): *(\S*).*?\n/i, '')) && !!$~ then
964
1106
  parse_comment_attr container, $1, $3, comment
965
1107
  end
966
1108
 
967
1109
  if co then
968
1110
  co.singleton = singleton
969
- co.offset = offset
970
1111
  co.line = line_no
971
1112
  end
972
1113
 
@@ -997,12 +1138,11 @@ class RDoc::Parser::Ruby < RDoc::Parser
997
1138
  record_location meth
998
1139
 
999
1140
  meth.start_collecting_tokens
1000
- indent = TkSPACE.new 0, 1, 1
1001
- indent.set_text " " * column
1002
-
1003
- position_comment = TkCOMMENT.new 0, line_no, 1
1004
- position_comment.set_text "# File #{@top_level.relative_name}, line #{line_no}"
1005
- meth.add_tokens [position_comment, NEWLINE_TOKEN, indent]
1141
+ indent = RDoc::Parser::RipperStateLex::Token.new(1, 1, :on_sp, ' ' * column)
1142
+ position_comment = RDoc::Parser::RipperStateLex::Token.new(line_no, 1, :on_comment)
1143
+ position_comment[:text] = "# File #{@top_level.relative_name}, line #{line_no}"
1144
+ newline = RDoc::Parser::RipperStateLex::Token.new(0, 0, :on_nl, "\n")
1145
+ meth.add_tokens [position_comment, newline, indent]
1006
1146
 
1007
1147
  meth.params =
1008
1148
  if text.sub!(/^#\s+:?args?:\s*(.*?)\s*$/i, '') then
@@ -1012,7 +1152,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
1012
1152
  end
1013
1153
 
1014
1154
  comment.normalize
1015
- comment.extract_call_seq meth
1155
+ meth.call_seq = comment.extract_call_seq
1016
1156
 
1017
1157
  return unless meth.name
1018
1158
 
@@ -1031,23 +1171,21 @@ class RDoc::Parser::Ruby < RDoc::Parser
1031
1171
 
1032
1172
  def parse_comment_tomdoc container, tk, comment
1033
1173
  return unless signature = RDoc::TomDoc.signature(comment)
1034
- offset = tk.seek
1035
- line_no = tk.line_no
1174
+ column = tk[:char_no]
1175
+ line_no = tk[:line_no]
1036
1176
 
1037
1177
  name, = signature.split %r%[ \(]%, 2
1038
1178
 
1039
1179
  meth = RDoc::GhostMethod.new get_tkread, name
1040
1180
  record_location meth
1041
- meth.offset = offset
1042
1181
  meth.line = line_no
1043
1182
 
1044
1183
  meth.start_collecting_tokens
1045
- indent = TkSPACE.new 0, 1, 1
1046
- indent.set_text " " * offset
1047
-
1048
- position_comment = TkCOMMENT.new 0, line_no, 1
1049
- position_comment.set_text "# File #{@top_level.relative_name}, line #{line_no}"
1050
- meth.add_tokens [position_comment, NEWLINE_TOKEN, indent]
1184
+ indent = RDoc::Parser::RipperStateLex::Token.new(1, 1, :on_sp, ' ' * column)
1185
+ position_comment = RDoc::Parser::RipperStateLex::Token.new(line_no, 1, :on_comment)
1186
+ position_comment[:text] = "# File #{@top_level.relative_name}, line #{line_no}"
1187
+ newline = RDoc::Parser::RipperStateLex::Token.new(0, 0, :on_nl, "\n")
1188
+ meth.add_tokens [position_comment, newline, indent]
1051
1189
 
1052
1190
  meth.call_seq = signature
1053
1191
 
@@ -1070,30 +1208,49 @@ class RDoc::Parser::Ruby < RDoc::Parser
1070
1208
  loop do
1071
1209
  skip_tkspace_comment
1072
1210
 
1073
- name = get_constant_with_optional_parens
1211
+ name = get_included_module_with_optional_parens
1074
1212
 
1075
1213
  unless name.empty? then
1076
1214
  obj = container.add klass, name, comment
1077
1215
  record_location obj
1078
1216
  end
1079
1217
 
1080
- return unless TkCOMMA === peek_tk
1218
+ return if peek_tk.nil? || :on_comma != peek_tk[:kind]
1081
1219
 
1082
1220
  get_tk
1083
1221
  end
1084
1222
  end
1085
1223
 
1224
+ ##
1225
+ # Parses an +included+ with a block feature of ActiveSupport::Concern.
1226
+
1227
+ def parse_included_with_activesupport_concern container, comment # :nodoc:
1228
+ skip_tkspace_without_nl
1229
+ tk = get_tk
1230
+ unless tk[:kind] == :on_lbracket || (tk[:kind] == :on_kw && tk[:text] == 'do')
1231
+ unget_tk tk
1232
+ return nil # should be a block
1233
+ end
1234
+
1235
+ parse_statements container
1236
+
1237
+ container
1238
+ end
1239
+
1086
1240
  ##
1087
1241
  # Parses identifiers that can create new methods or change visibility.
1088
1242
  #
1089
1243
  # Returns true if the comment was not consumed.
1090
1244
 
1091
1245
  def parse_identifier container, single, tk, comment # :nodoc:
1092
- case tk.name
1246
+ case tk[:text]
1093
1247
  when 'private', 'protected', 'public', 'private_class_method',
1094
1248
  'public_class_method', 'module_function' then
1095
1249
  parse_visibility container, single, tk
1096
1250
  return true
1251
+ when 'private_constant', 'public_constant'
1252
+ parse_constant_visibility container, single, tk
1253
+ return true
1097
1254
  when 'attr' then
1098
1255
  parse_attr container, single, tk, comment
1099
1256
  when /^attr_(reader|writer|accessor)$/ then
@@ -1158,7 +1315,9 @@ class RDoc::Parser::Ruby < RDoc::Parser
1158
1315
  tmp = RDoc::CodeObject.new
1159
1316
  read_documentation_modifiers tmp, RDoc::ATTR_MODIFIERS
1160
1317
 
1161
- if comment.text.sub!(/^# +:?(attr(_reader|_writer|_accessor)?): *(\S*).*?\n/i, '') then
1318
+ regexp = /^# +:?(attr(_reader|_writer|_accessor)?): *(\S*).*?\n/i
1319
+ if regexp =~ comment.text then
1320
+ comment.text = comment.text.sub(regexp, '')
1162
1321
  rw = case $1
1163
1322
  when 'attr_reader' then 'R'
1164
1323
  when 'attr_writer' then 'W'
@@ -1182,37 +1341,34 @@ class RDoc::Parser::Ruby < RDoc::Parser
1182
1341
  # Parses a meta-programmed method
1183
1342
 
1184
1343
  def parse_meta_method(container, single, tk, comment)
1185
- column = tk.char_no
1186
- offset = tk.seek
1187
- line_no = tk.line_no
1344
+ column = tk[:char_no]
1345
+ line_no = tk[:line_no]
1188
1346
 
1189
1347
  start_collecting_tokens
1190
1348
  add_token tk
1191
1349
  add_token_listener self
1192
1350
 
1193
- skip_tkspace false
1351
+ skip_tkspace_without_nl
1194
1352
 
1195
- singleton = !!comment.text.sub!(/(^# +:?)(singleton-)(method:)/, '\1\3')
1353
+ comment.text = comment.text.sub(/(^# +:?)(singleton-)(method:)/, '\1\3')
1354
+ singleton = !!$~
1196
1355
 
1197
1356
  name = parse_meta_method_name comment, tk
1198
1357
 
1199
1358
  return unless name
1200
1359
 
1201
- meth = RDoc::MetaMethod.new get_tkread, name
1360
+ meth = RDoc::MetaMethod.new get_tkread, name, singleton: singleton
1202
1361
  record_location meth
1203
- meth.offset = offset
1204
1362
  meth.line = line_no
1205
- meth.singleton = singleton
1206
1363
 
1207
1364
  remove_token_listener self
1208
1365
 
1209
1366
  meth.start_collecting_tokens
1210
- indent = TkSPACE.new 0, 1, 1
1211
- indent.set_text " " * column
1212
-
1213
- position_comment = TkCOMMENT.new 0, line_no, 1
1214
- position_comment.value = "# File #{@top_level.relative_name}, line #{line_no}"
1215
- meth.add_tokens [position_comment, NEWLINE_TOKEN, indent]
1367
+ indent = RDoc::Parser::RipperStateLex::Token.new(1, 1, :on_sp, ' ' * column)
1368
+ position_comment = RDoc::Parser::RipperStateLex::Token.new(line_no, 1, :on_comment)
1369
+ position_comment[:text] = "# File #{@top_level.relative_name}, line #{line_no}"
1370
+ newline = RDoc::Parser::RipperStateLex::Token.new(0, 0, :on_nl, "\n")
1371
+ meth.add_tokens [position_comment, newline, indent]
1216
1372
  meth.add_tokens @token_stream
1217
1373
 
1218
1374
  parse_meta_method_params container, single, meth, tk, comment
@@ -1236,17 +1392,16 @@ class RDoc::Parser::Ruby < RDoc::Parser
1236
1392
 
1237
1393
  name_t = get_tk
1238
1394
 
1239
- case name_t
1240
- when TkSYMBOL then
1241
- name_t.text[1..-1]
1242
- when TkSTRING then
1243
- name_t.value[1..-2]
1244
- when TkASSIGN then # ignore
1395
+ if :on_symbol == name_t[:kind] then
1396
+ name_t[:text][1..-1]
1397
+ elsif :on_tstring == name_t[:kind] then
1398
+ name_t[:text][1..-2]
1399
+ elsif :on_op == name_t[:kind] && '=' == name_t[:text] then # ignore
1245
1400
  remove_token_listener self
1246
1401
 
1247
1402
  nil
1248
1403
  else
1249
- warn "unknown name token #{name_t.inspect} for meta-method '#{tk.name}'"
1404
+ warn "unknown name token #{name_t.inspect} for meta-method '#{tk[:text]}'"
1250
1405
  'unknown'
1251
1406
  end
1252
1407
  end
@@ -1258,22 +1413,22 @@ class RDoc::Parser::Ruby < RDoc::Parser
1258
1413
  token_listener meth do
1259
1414
  meth.params = ''
1260
1415
 
1416
+ look_for_directives_in meth, comment
1261
1417
  comment.normalize
1262
- comment.extract_call_seq meth
1418
+ meth.call_seq = comment.extract_call_seq
1263
1419
 
1264
1420
  container.add_method meth
1265
1421
 
1266
1422
  last_tk = tk
1267
1423
 
1268
1424
  while tk = get_tk do
1269
- case tk
1270
- when TkSEMICOLON then
1425
+ if :on_semicolon == tk[:kind] then
1271
1426
  break
1272
- when TkNL then
1273
- break unless last_tk and TkCOMMA === last_tk
1274
- when TkSPACE then
1427
+ elsif :on_nl == tk[:kind] then
1428
+ break unless last_tk and :on_comma == last_tk[:kind]
1429
+ elsif :on_sp == tk[:kind] then
1275
1430
  # expression continues
1276
- when TkDO then
1431
+ elsif :on_kw == tk[:kind] && 'do' == tk[:text] then
1277
1432
  parse_statements container, single, meth
1278
1433
  break
1279
1434
  else
@@ -1290,9 +1445,8 @@ class RDoc::Parser::Ruby < RDoc::Parser
1290
1445
  singleton = nil
1291
1446
  added_container = false
1292
1447
  name = nil
1293
- column = tk.char_no
1294
- offset = tk.seek
1295
- line_no = tk.line_no
1448
+ column = tk[:char_no]
1449
+ line_no = tk[:line_no]
1296
1450
 
1297
1451
  start_collecting_tokens
1298
1452
  add_token tk
@@ -1305,29 +1459,36 @@ class RDoc::Parser::Ruby < RDoc::Parser
1305
1459
 
1306
1460
  return unless name
1307
1461
 
1308
- meth = RDoc::AnyMethod.new get_tkread, name
1309
- meth.singleton = single == SINGLE ? true : singleton
1462
+ meth = RDoc::AnyMethod.new get_tkread, name, singleton: single == SINGLE ? true : singleton
1463
+ look_for_directives_in meth, comment
1464
+ if singleton
1465
+ # `current_line_visibility' is useless because it works against
1466
+ # the normal method named as same as the singleton method, after
1467
+ # the latter was defined. Of course these are different things.
1468
+ container.current_line_visibility = :public
1469
+ end
1310
1470
 
1311
1471
  record_location meth
1312
- meth.offset = offset
1313
1472
  meth.line = line_no
1314
1473
 
1315
1474
  meth.start_collecting_tokens
1316
- indent = TkSPACE.new 0, 1, 1
1317
- indent.set_text " " * column
1318
-
1319
- token = TkCOMMENT.new 0, line_no, 1
1320
- token.set_text "# File #{@top_level.relative_name}, line #{line_no}"
1321
- meth.add_tokens [token, NEWLINE_TOKEN, indent]
1475
+ indent = RDoc::Parser::RipperStateLex::Token.new(1, 1, :on_sp, ' ' * column)
1476
+ token = RDoc::Parser::RipperStateLex::Token.new(line_no, 1, :on_comment)
1477
+ token[:text] = "# File #{@top_level.relative_name}, line #{line_no}"
1478
+ newline = RDoc::Parser::RipperStateLex::Token.new(0, 0, :on_nl, "\n")
1479
+ meth.add_tokens [token, newline, indent]
1322
1480
  meth.add_tokens @token_stream
1323
1481
 
1324
1482
  parse_method_params_and_body container, single, meth, added_container
1325
1483
 
1326
1484
  comment.normalize
1327
- comment.extract_call_seq meth
1485
+ meth.call_seq = comment.extract_call_seq
1328
1486
 
1329
1487
  meth.comment = comment
1330
1488
 
1489
+ # after end modifiers
1490
+ read_documentation_modifiers meth, RDoc::METHOD_MODIFIERS
1491
+
1331
1492
  @stats.add_method meth
1332
1493
  end
1333
1494
 
@@ -1336,7 +1497,6 @@ class RDoc::Parser::Ruby < RDoc::Parser
1336
1497
 
1337
1498
  def parse_method_params_and_body container, single, meth, added_container
1338
1499
  token_listener meth do
1339
- @scanner.continue = false
1340
1500
  parse_method_parameters meth
1341
1501
 
1342
1502
  if meth.document_self or not @track_visibility then
@@ -1379,15 +1539,13 @@ class RDoc::Parser::Ruby < RDoc::Parser
1379
1539
  # it is a singleton or regular method.
1380
1540
 
1381
1541
  def parse_method_name container # :nodoc:
1382
- @scanner.lex_state = :EXPR_FNAME
1383
-
1384
1542
  skip_tkspace
1385
1543
  name_t = get_tk
1386
- back_tk = skip_tkspace
1544
+ back_tk = skip_tkspace_without_nl
1387
1545
  singleton = false
1388
1546
 
1389
- case dot = get_tk
1390
- when TkDOT, TkCOLON2 then
1547
+ dot = get_tk
1548
+ if dot[:kind] == :on_period || (dot[:kind] == :on_op && dot[:text] == '::') then
1391
1549
  singleton = true
1392
1550
 
1393
1551
  name, container = parse_method_name_singleton container, name_t
@@ -1408,16 +1566,15 @@ class RDoc::Parser::Ruby < RDoc::Parser
1408
1566
  # is parsed from the token stream for a regular method.
1409
1567
 
1410
1568
  def parse_method_name_regular container, name_t # :nodoc:
1411
- case name_t
1412
- when TkSTAR, TkAMPER then
1413
- name_t.text
1569
+ if :on_op == name_t[:kind] && (%w{* & [] []= <<}.include?(name_t[:text])) then
1570
+ name_t[:text]
1414
1571
  else
1415
- unless name_t.respond_to? :name then
1572
+ unless [:on_kw, :on_const, :on_ident].include?(name_t[:kind]) then
1416
1573
  warn "expected method name token, . or ::, got #{name_t.inspect}"
1417
1574
  skip_method container
1418
1575
  return
1419
1576
  end
1420
- name_t.name
1577
+ name_t[:text]
1421
1578
  end
1422
1579
  end
1423
1580
 
@@ -1427,47 +1584,42 @@ class RDoc::Parser::Ruby < RDoc::Parser
1427
1584
  # for a singleton method.
1428
1585
 
1429
1586
  def parse_method_name_singleton container, name_t # :nodoc:
1430
- @scanner.lex_state = :EXPR_FNAME
1431
1587
  skip_tkspace
1432
1588
  name_t2 = get_tk
1433
1589
 
1434
- name =
1435
- case name_t
1436
- when TkSELF, TkMOD then
1437
- case name_t2
1438
- # NOTE: work around '[' being consumed early and not being re-tokenized
1439
- # as a TkAREF
1440
- when TkfLBRACK then
1441
- get_tk
1442
- '[]'
1443
- else
1444
- name_t2.name
1445
- end
1446
- when TkCONSTANT then
1447
- name = name_t2.name
1590
+ if (:on_kw == name_t[:kind] && 'self' == name_t[:text]) || (:on_op == name_t[:kind] && '%' == name_t[:text]) then
1591
+ # NOTE: work around '[' being consumed early
1592
+ if :on_lbracket == name_t2[:kind]
1593
+ get_tk
1594
+ name = '[]'
1595
+ else
1596
+ name = name_t2[:text]
1597
+ end
1598
+ elsif :on_const == name_t[:kind] then
1599
+ name = name_t2[:text]
1448
1600
 
1449
- container = get_method_container container, name_t
1601
+ container = get_method_container container, name_t
1450
1602
 
1451
- return unless container
1603
+ return unless container
1452
1604
 
1453
- name
1454
- when TkIDENTIFIER, TkIVAR, TkGVAR then
1455
- parse_method_dummy container
1605
+ name
1606
+ elsif :on_ident == name_t[:kind] || :on_ivar == name_t[:kind] || :on_gvar == name_t[:kind] then
1607
+ parse_method_dummy container
1456
1608
 
1457
- nil
1458
- when TkTRUE, TkFALSE, TkNIL then
1459
- klass_name = "#{name_t.name.capitalize}Class"
1460
- container = @store.find_class_named klass_name
1461
- container ||= @top_level.add_class RDoc::NormalClass, klass_name
1609
+ name = nil
1610
+ elsif (:on_kw == name_t[:kind]) && ('true' == name_t[:text] || 'false' == name_t[:text] || 'nil' == name_t[:text]) then
1611
+ klass_name = "#{name_t[:text].capitalize}Class"
1612
+ container = @store.find_class_named klass_name
1613
+ container ||= @top_level.add_class RDoc::NormalClass, klass_name
1462
1614
 
1463
- name_t2.name
1464
- else
1465
- warn "unexpected method name token #{name_t.inspect}"
1466
- # break
1467
- skip_method container
1615
+ name = name_t2[:text]
1616
+ else
1617
+ warn "unexpected method name token #{name_t.inspect}"
1618
+ # break
1619
+ skip_method container
1468
1620
 
1469
- nil
1470
- end
1621
+ name = nil
1622
+ end
1471
1623
 
1472
1624
  return name, container
1473
1625
  end
@@ -1477,45 +1629,56 @@ class RDoc::Parser::Ruby < RDoc::Parser
1477
1629
 
1478
1630
  def parse_method_or_yield_parameters(method = nil,
1479
1631
  modifiers = RDoc::METHOD_MODIFIERS)
1480
- skip_tkspace false
1632
+ skip_tkspace_without_nl
1481
1633
  tk = get_tk
1482
1634
  end_token = get_end_token tk
1483
1635
  return '' unless end_token
1484
1636
 
1485
1637
  nest = 0
1638
+ continue = false
1486
1639
 
1487
- loop do
1488
- case tk
1489
- when TkSEMICOLON then
1640
+ while tk != nil do
1641
+ case tk[:kind]
1642
+ when :on_semicolon then
1490
1643
  break if nest == 0
1491
- when TkLBRACE, TkfLBRACE then
1644
+ when :on_lbracket then
1492
1645
  nest += 1
1493
- when TkRBRACE then
1646
+ when :on_rbracket then
1647
+ nest -= 1
1648
+ when :on_lbrace then
1649
+ nest += 1
1650
+ when :on_rbrace then
1494
1651
  nest -= 1
1495
1652
  if nest <= 0
1496
1653
  # we might have a.each { |i| yield i }
1497
1654
  unget_tk(tk) if nest < 0
1498
1655
  break
1499
1656
  end
1500
- when TkLPAREN, TkfLPAREN then
1657
+ when :on_lparen then
1501
1658
  nest += 1
1502
- when end_token then
1503
- if end_token == TkRPAREN
1659
+ when end_token[:kind] then
1660
+ if end_token[:kind] == :on_rparen
1504
1661
  nest -= 1
1505
1662
  break if nest <= 0
1506
1663
  else
1507
- break unless @scanner.continue
1664
+ break
1508
1665
  end
1509
- when TkRPAREN then
1666
+ when :on_rparen then
1510
1667
  nest -= 1
1511
- when method && method.block_params.nil? && TkCOMMENT then
1512
- unget_tk tk
1513
- read_documentation_modifiers method, modifiers
1514
- @read.pop
1515
- when TkCOMMENT then
1668
+ when :on_comment, :on_embdoc then
1516
1669
  @read.pop
1517
- when nil then
1518
- break
1670
+ if :on_nl == end_token[:kind] and "\n" == tk[:text][-1] and
1671
+ (!continue or (tk[:state] & Ripper::EXPR_LABEL) != 0) then
1672
+ if method && method.block_params.nil? then
1673
+ unget_tk tk
1674
+ read_documentation_modifiers method, modifiers
1675
+ end
1676
+ break if !continue and nest <= 0
1677
+ end
1678
+ when :on_comma then
1679
+ continue = true
1680
+ when :on_ident then
1681
+ continue = false if continue
1519
1682
  end
1520
1683
  tk = get_tk
1521
1684
  end
@@ -1539,7 +1702,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
1539
1702
 
1540
1703
  return if method.block_params
1541
1704
 
1542
- skip_tkspace false
1705
+ skip_tkspace_without_nl
1543
1706
  read_documentation_modifiers method, RDoc::METHOD_MODIFIERS
1544
1707
  end
1545
1708
 
@@ -1549,7 +1712,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
1549
1712
  def parse_module container, single, tk, comment
1550
1713
  container, name_t, = get_class_or_module container
1551
1714
 
1552
- name = name_t.name
1715
+ name = name_t[:text]
1553
1716
 
1554
1717
  mod = container.add_module RDoc::NormalModule, name
1555
1718
  mod.ignore unless container.document_children
@@ -1559,6 +1722,9 @@ class RDoc::Parser::Ruby < RDoc::Parser
1559
1722
  mod.add_comment comment, @top_level
1560
1723
  parse_statements mod
1561
1724
 
1725
+ # after end modifiers
1726
+ read_documentation_modifiers mod, RDoc::CLASS_MODIFIERS
1727
+
1562
1728
  @stats.add_module mod
1563
1729
  end
1564
1730
 
@@ -1569,12 +1735,12 @@ class RDoc::Parser::Ruby < RDoc::Parser
1569
1735
  skip_tkspace_comment
1570
1736
  tk = get_tk
1571
1737
 
1572
- if TkLPAREN === tk then
1738
+ if :on_lparen == tk[:kind] then
1573
1739
  skip_tkspace_comment
1574
1740
  tk = get_tk
1575
1741
  end
1576
1742
 
1577
- name = tk.text if TkSTRING === tk
1743
+ name = tk[:text][1..-2] if :on_tstring == tk[:kind]
1578
1744
 
1579
1745
  if name then
1580
1746
  @top_level.add_require RDoc::Require.new(name, comment)
@@ -1587,19 +1753,30 @@ class RDoc::Parser::Ruby < RDoc::Parser
1587
1753
  # Parses a rescue
1588
1754
 
1589
1755
  def parse_rescue
1590
- skip_tkspace false
1756
+ skip_tkspace_without_nl
1591
1757
 
1592
1758
  while tk = get_tk
1593
- case tk
1594
- when TkNL, TkSEMICOLON then
1759
+ case tk[:kind]
1760
+ when :on_nl, :on_semicolon, :on_comment then
1595
1761
  break
1596
- when TkCOMMA then
1597
- skip_tkspace false
1762
+ when :on_comma then
1763
+ skip_tkspace_without_nl
1598
1764
 
1599
- get_tk if TkNL === peek_tk
1765
+ get_tk if :on_nl == peek_tk[:kind]
1600
1766
  end
1601
1767
 
1602
- skip_tkspace false
1768
+ skip_tkspace_without_nl
1769
+ end
1770
+ end
1771
+
1772
+ ##
1773
+ # Retrieve comment body without =begin/=end
1774
+
1775
+ def retrieve_comment_body(tk)
1776
+ if :on_embdoc == tk[:kind]
1777
+ tk[:text].gsub(/\A=begin.*\n/, '').gsub(/=end\n?\z/, '')
1778
+ else
1779
+ tk[:text]
1603
1780
  end
1604
1781
  end
1605
1782
 
@@ -1609,10 +1786,11 @@ class RDoc::Parser::Ruby < RDoc::Parser
1609
1786
  def parse_statements(container, single = NORMAL, current_method = nil,
1610
1787
  comment = new_comment(''))
1611
1788
  raise 'no' unless RDoc::Comment === comment
1612
- comment.force_encoding @encoding if @encoding
1789
+ comment = RDoc::Encoding.change_encoding comment, @encoding if @encoding
1613
1790
 
1614
1791
  nest = 1
1615
1792
  save_visibility = container.visibility
1793
+ container.visibility = :public unless current_method
1616
1794
 
1617
1795
  non_comment_seen = true
1618
1796
 
@@ -1620,35 +1798,55 @@ class RDoc::Parser::Ruby < RDoc::Parser
1620
1798
  keep_comment = false
1621
1799
  try_parse_comment = false
1622
1800
 
1623
- non_comment_seen = true unless TkCOMMENT === tk
1801
+ non_comment_seen = true unless (:on_comment == tk[:kind] or :on_embdoc == tk[:kind])
1624
1802
 
1625
- case tk
1626
- when TkNL then
1627
- skip_tkspace
1628
- tk = get_tk
1803
+ case tk[:kind]
1804
+ when :on_nl, :on_ignored_nl, :on_comment, :on_embdoc then
1805
+ if :on_nl == tk[:kind] or :on_ignored_nl == tk[:kind]
1806
+ skip_tkspace
1807
+ tk = get_tk
1808
+ else
1809
+ past_tokens = @read.size > 1 ? @read[0..-2] : []
1810
+ nl_position = 0
1811
+ past_tokens.reverse.each_with_index do |read_tk, i|
1812
+ if read_tk =~ /^\n$/ then
1813
+ nl_position = (past_tokens.size - 1) - i
1814
+ break
1815
+ elsif read_tk =~ /^#.*\n$/ then
1816
+ nl_position = ((past_tokens.size - 1) - i) + 1
1817
+ break
1818
+ end
1819
+ end
1820
+ comment_only_line = past_tokens[nl_position..-1].all?{ |c| c =~ /^\s+$/ }
1821
+ unless comment_only_line then
1822
+ tk = get_tk
1823
+ end
1824
+ end
1629
1825
 
1630
- if TkCOMMENT === tk then
1826
+ if tk and (:on_comment == tk[:kind] or :on_embdoc == tk[:kind]) then
1631
1827
  if non_comment_seen then
1632
1828
  # Look for RDoc in a comment about to be thrown away
1633
1829
  non_comment_seen = parse_comment container, tk, comment unless
1634
1830
  comment.empty?
1635
1831
 
1636
1832
  comment = ''
1637
- comment.force_encoding @encoding if @encoding
1833
+ comment = RDoc::Encoding.change_encoding comment, @encoding if @encoding
1638
1834
  end
1639
1835
 
1640
- while TkCOMMENT === tk do
1641
- comment << tk.text << "\n"
1836
+ line_no = nil
1837
+ while tk and (:on_comment == tk[:kind] or :on_embdoc == tk[:kind]) do
1838
+ comment_body = retrieve_comment_body(tk)
1839
+ line_no = tk[:line_no] if comment.empty?
1840
+ comment += comment_body
1841
+ comment << "\n" unless comment_body =~ /\n\z/
1642
1842
 
1643
- tk = get_tk
1644
-
1645
- if TkNL === tk then
1646
- skip_tkspace false # leading spaces
1647
- tk = get_tk
1843
+ if comment_body.size > 1 && comment_body =~ /\n\z/ then
1844
+ skip_tkspace_without_nl # leading spaces
1648
1845
  end
1846
+ tk = get_tk
1649
1847
  end
1650
1848
 
1651
- comment = new_comment comment
1849
+ comment = new_comment comment, line_no
1652
1850
 
1653
1851
  unless comment.empty? then
1654
1852
  look_for_directives_in container, comment
@@ -1668,77 +1866,86 @@ class RDoc::Parser::Ruby < RDoc::Parser
1668
1866
  keep_comment = true
1669
1867
  container.current_line_visibility = nil
1670
1868
 
1671
- when TkCLASS then
1672
- parse_class container, single, tk, comment
1869
+ when :on_kw then
1870
+ case tk[:text]
1871
+ when 'class' then
1872
+ parse_class container, single, tk, comment
1673
1873
 
1674
- when TkMODULE then
1675
- parse_module container, single, tk, comment
1874
+ when 'module' then
1875
+ parse_module container, single, tk, comment
1676
1876
 
1677
- when TkDEF then
1678
- parse_method container, single, tk, comment
1877
+ when 'def' then
1878
+ parse_method container, single, tk, comment
1679
1879
 
1680
- when TkCONSTANT then
1681
- unless parse_constant container, tk, comment, current_method then
1682
- try_parse_comment = true
1683
- end
1880
+ when 'alias' then
1881
+ parse_alias container, single, tk, comment unless current_method
1684
1882
 
1685
- when TkALIAS then
1686
- parse_alias container, single, tk, comment unless current_method
1883
+ when 'yield' then
1884
+ if current_method.nil? then
1885
+ warn "Warning: yield outside of method" if container.document_self
1886
+ else
1887
+ parse_yield container, single, tk, current_method
1888
+ end
1687
1889
 
1688
- when TkYIELD then
1689
- if current_method.nil? then
1690
- warn "Warning: yield outside of method" if container.document_self
1691
- else
1692
- parse_yield container, single, tk, current_method
1693
- end
1890
+ when 'until', 'while' then
1891
+ if (tk[:state] & Ripper::EXPR_LABEL) == 0
1892
+ nest += 1
1893
+ skip_optional_do_after_expression
1894
+ end
1694
1895
 
1695
- # Until and While can have a 'do', which shouldn't increase the nesting.
1696
- # We can't solve the general case, but we can handle most occurrences by
1697
- # ignoring a do at the end of a line.
1896
+ # Until and While can have a 'do', which shouldn't increase the nesting.
1897
+ # We can't solve the general case, but we can handle most occurrences by
1898
+ # ignoring a do at the end of a line.
1698
1899
 
1699
- when TkUNTIL, TkWHILE then
1700
- nest += 1
1701
- skip_optional_do_after_expression
1900
+ # 'for' is trickier
1901
+ when 'for' then
1902
+ nest += 1
1903
+ skip_for_variable
1904
+ skip_optional_do_after_expression
1702
1905
 
1703
- # 'for' is trickier
1704
- when TkFOR then
1705
- nest += 1
1706
- skip_for_variable
1707
- skip_optional_do_after_expression
1906
+ when 'case', 'do', 'if', 'unless', 'begin' then
1907
+ if (tk[:state] & Ripper::EXPR_LABEL) == 0
1908
+ nest += 1
1909
+ end
1708
1910
 
1709
- when TkCASE, TkDO, TkIF, TkUNLESS, TkBEGIN then
1710
- nest += 1
1911
+ when 'super' then
1912
+ current_method.calls_super = true if current_method
1913
+
1914
+ when 'rescue' then
1915
+ parse_rescue
1711
1916
 
1712
- when TkSUPER then
1713
- current_method.calls_super = true if current_method
1917
+ when 'end' then
1918
+ nest -= 1
1919
+ if nest == 0 then
1920
+ container.ongoing_visibility = save_visibility
1921
+
1922
+ parse_comment container, tk, comment unless comment.empty?
1714
1923
 
1715
- when TkRESCUE then
1716
- parse_rescue
1924
+ return
1925
+ end
1926
+ end
1717
1927
 
1718
- when TkIDENTIFIER then
1928
+ when :on_const then
1929
+ unless parse_constant container, tk, comment, current_method then
1930
+ try_parse_comment = true
1931
+ end
1932
+
1933
+ when :on_ident then
1719
1934
  if nest == 1 and current_method.nil? then
1720
1935
  keep_comment = parse_identifier container, single, tk, comment
1721
1936
  end
1722
1937
 
1723
- case tk.name
1938
+ case tk[:text]
1724
1939
  when "require" then
1725
1940
  parse_require container, comment
1726
1941
  when "include" then
1727
1942
  parse_extend_or_include RDoc::Include, container, comment
1728
1943
  when "extend" then
1729
1944
  parse_extend_or_include RDoc::Extend, container, comment
1945
+ when "included" then
1946
+ parse_included_with_activesupport_concern container, comment
1730
1947
  end
1731
1948
 
1732
- when TkEND then
1733
- nest -= 1
1734
- if nest == 0 then
1735
- read_documentation_modifiers container, RDoc::CLASS_MODIFIERS
1736
- container.ongoing_visibility = save_visibility
1737
-
1738
- parse_comment container, tk, comment unless comment.empty?
1739
-
1740
- return
1741
- end
1742
1949
  else
1743
1950
  try_parse_comment = nest == 1
1744
1951
  end
@@ -1752,7 +1959,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
1752
1959
 
1753
1960
  unless keep_comment then
1754
1961
  comment = new_comment ''
1755
- comment.force_encoding @encoding if @encoding
1962
+ comment = RDoc::Encoding.change_encoding comment, @encoding if @encoding
1756
1963
  container.params = nil
1757
1964
  container.block_params = nil
1758
1965
  end
@@ -1770,8 +1977,8 @@ class RDoc::Parser::Ruby < RDoc::Parser
1770
1977
  def parse_symbol_arg(no = nil)
1771
1978
  skip_tkspace_comment
1772
1979
 
1773
- case tk = get_tk
1774
- when TkLPAREN
1980
+ tk = get_tk
1981
+ if tk[:kind] == :on_lparen
1775
1982
  parse_symbol_arg_paren no
1776
1983
  else
1777
1984
  parse_symbol_arg_space no, tk
@@ -1793,10 +2000,10 @@ class RDoc::Parser::Ruby < RDoc::Parser
1793
2000
  end
1794
2001
 
1795
2002
  skip_tkspace_comment
1796
- case tk2 = get_tk
1797
- when TkRPAREN
2003
+ case (tk2 = get_tk)[:kind]
2004
+ when :on_rparen
1798
2005
  break
1799
- when TkCOMMA
2006
+ when :on_comma
1800
2007
  else
1801
2008
  warn("unexpected token: '#{tk2.inspect}'") if $DEBUG_RDOC
1802
2009
  break
@@ -1820,10 +2027,10 @@ class RDoc::Parser::Ruby < RDoc::Parser
1820
2027
  end
1821
2028
 
1822
2029
  loop do
1823
- skip_tkspace false
2030
+ skip_tkspace_without_nl
1824
2031
 
1825
2032
  tk1 = get_tk
1826
- unless TkCOMMA === tk1 then
2033
+ if tk1.nil? || :on_comma != tk1[:kind] then
1827
2034
  unget_tk tk1
1828
2035
  break
1829
2036
  end
@@ -1842,12 +2049,12 @@ class RDoc::Parser::Ruby < RDoc::Parser
1842
2049
  # Returns symbol text from the next token
1843
2050
 
1844
2051
  def parse_symbol_in_arg
1845
- case tk = get_tk
1846
- when TkSYMBOL
1847
- tk.text.sub(/^:/, '')
1848
- when TkSTRING
1849
- eval @read[-1]
1850
- when TkDSTRING, TkIDENTIFIER then
2052
+ tk = get_tk
2053
+ if :on_symbol == tk[:kind] then
2054
+ tk[:text].sub(/^:/, '')
2055
+ elsif :on_tstring == tk[:kind] then
2056
+ tk[:text][1..-2]
2057
+ elsif :on_dstring == tk[:kind] or :on_ident == tk[:kind] then
1851
2058
  nil # ignore
1852
2059
  else
1853
2060
  warn("Expected symbol or string, got #{tk.inspect}") if $DEBUG_RDOC
@@ -1881,21 +2088,37 @@ class RDoc::Parser::Ruby < RDoc::Parser
1881
2088
 
1882
2089
  skip_tkspace_comment false
1883
2090
 
1884
- case peek_tk
1885
- # Ryan Davis suggested the extension to ignore modifiers, because he
1886
- # often writes
1887
- #
1888
- # protected unless $TESTING
1889
- #
1890
- when TkNL, TkUNLESS_MOD, TkIF_MOD, TkSEMICOLON then
2091
+ ptk = peek_tk
2092
+ # Ryan Davis suggested the extension to ignore modifiers, because he
2093
+ # often writes
2094
+ #
2095
+ # protected unless $TESTING
2096
+ #
2097
+ if [:on_nl, :on_semicolon].include?(ptk[:kind]) || (:on_kw == ptk[:kind] && (['if', 'unless'].include?(ptk[:text]))) then
1891
2098
  container.ongoing_visibility = vis
1892
- when TkDEF
2099
+ elsif :on_kw == ptk[:kind] && 'def' == ptk[:text]
1893
2100
  container.current_line_visibility = vis
1894
2101
  else
1895
2102
  update_visibility container, vis_type, vis, singleton
1896
2103
  end
1897
2104
  end
1898
2105
 
2106
+ ##
2107
+ # Parses a Module#private_constant or Module#public_constant call from +tk+.
2108
+
2109
+ def parse_constant_visibility(container, single, tk)
2110
+ args = parse_symbol_arg
2111
+ case tk[:text]
2112
+ when 'private_constant'
2113
+ vis = :private
2114
+ when 'public_constant'
2115
+ vis = :public
2116
+ else
2117
+ raise RDoc::Error, 'Unreachable'
2118
+ end
2119
+ container.set_constant_visibility_for args, vis
2120
+ end
2121
+
1899
2122
  ##
1900
2123
  # Determines the block parameter for +context+
1901
2124
 
@@ -1903,7 +2126,6 @@ class RDoc::Parser::Ruby < RDoc::Parser
1903
2126
  return if method.block_params
1904
2127
 
1905
2128
  get_tkread
1906
- @scanner.continue = false
1907
2129
  method.block_params = parse_method_or_yield_parameters
1908
2130
  end
1909
2131
 
@@ -1927,11 +2149,10 @@ class RDoc::Parser::Ruby < RDoc::Parser
1927
2149
  while tk = get_tk do
1928
2150
  tokens << tk
1929
2151
 
1930
- case tk
1931
- when TkNL, TkDEF then
2152
+ if :on_nl == tk[:kind] or (:on_kw == tk[:kind] && 'def' == tk[:text]) then
1932
2153
  return
1933
- when TkCOMMENT then
1934
- return unless tk.text =~ /\s*:?([\w-]+):\s*(.*)/
2154
+ elsif :on_comment == tk[:kind] or :on_embdoc == tk[:kind] then
2155
+ return unless tk[:text] =~ /:?\b([\w-]+):\s*(.*)/
1935
2156
 
1936
2157
  directive = $1.downcase
1937
2158
 
@@ -1941,7 +2162,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
1941
2162
  end
1942
2163
  end
1943
2164
  ensure
1944
- unless tokens.length == 1 and TkCOMMENT === tokens.first then
2165
+ unless tokens.length == 1 and (:on_comment == tokens.first[:kind] or :on_embdoc == tokens.first[:kind]) then
1945
2166
  tokens.reverse_each do |token|
1946
2167
  unget_tk token
1947
2168
  end
@@ -1955,6 +2176,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
1955
2176
  # See also RDoc::Markup::PreProcess#handle_directive
1956
2177
 
1957
2178
  def read_documentation_modifiers context, allowed
2179
+ skip_tkspace_without_nl
1958
2180
  directive, value = read_directive allowed
1959
2181
 
1960
2182
  return unless directive
@@ -1981,15 +2203,6 @@ class RDoc::Parser::Ruby < RDoc::Parser
1981
2203
  container.record_location @top_level
1982
2204
  end
1983
2205
 
1984
- ##
1985
- # Removes private comments from +comment+
1986
- #--
1987
- # TODO remove
1988
-
1989
- def remove_private_comments comment
1990
- comment.remove_private
1991
- end
1992
-
1993
2206
  ##
1994
2207
  # Scans this Ruby file for Ruby constructs
1995
2208
 
@@ -2001,29 +2214,33 @@ class RDoc::Parser::Ruby < RDoc::Parser
2001
2214
  parse_top_level_statements @top_level
2002
2215
 
2003
2216
  rescue StandardError => e
2004
- bytes = ''
2005
-
2006
- 20.times do @scanner.ungetc end
2007
- count = 0
2008
- 60.times do |i|
2009
- count = i
2010
- byte = @scanner.getc
2011
- break unless byte
2012
- bytes << byte
2217
+ if @content.include?('<%') and @content.include?('%>') then
2218
+ # Maybe, this is ERB.
2219
+ $stderr.puts "\033[2KRDoc detects ERB file. Skips it for compatibility:"
2220
+ $stderr.puts @file_name
2221
+ return
2222
+ end
2223
+
2224
+ if @scanner_point >= @scanner.size
2225
+ now_line_no = @scanner[@scanner.size - 1][:line_no]
2226
+ else
2227
+ now_line_no = peek_tk[:line_no]
2013
2228
  end
2014
- count -= 20
2015
- count.times do @scanner.ungetc end
2229
+ first_tk_index = @scanner.find_index { |tk| tk[:line_no] == now_line_no }
2230
+ last_tk_index = @scanner.find_index { |tk| tk[:line_no] == now_line_no + 1 }
2231
+ last_tk_index = last_tk_index ? last_tk_index - 1 : @scanner.size - 1
2232
+ code = @scanner[first_tk_index..last_tk_index].map{ |t| t[:text] }.join
2016
2233
 
2017
2234
  $stderr.puts <<-EOF
2018
2235
 
2019
- #{self.class} failure around line #{@scanner.line_no} of
2236
+ #{self.class} failure around line #{now_line_no} of
2020
2237
  #{@file_name}
2021
2238
 
2022
2239
  EOF
2023
2240
 
2024
- unless bytes.empty? then
2241
+ unless code.empty? then
2242
+ $stderr.puts code
2025
2243
  $stderr.puts
2026
- $stderr.puts bytes.inspect
2027
2244
  end
2028
2245
 
2029
2246
  raise e
@@ -2037,53 +2254,52 @@ class RDoc::Parser::Ruby < RDoc::Parser
2037
2254
  # while, until, and for have an optional do
2038
2255
 
2039
2256
  def skip_optional_do_after_expression
2040
- skip_tkspace false
2257
+ skip_tkspace_without_nl
2041
2258
  tk = get_tk
2042
- end_token = get_end_token tk
2043
2259
 
2044
2260
  b_nest = 0
2045
2261
  nest = 0
2046
- @scanner.continue = false
2047
2262
 
2048
2263
  loop do
2049
- case tk
2050
- when TkSEMICOLON then
2264
+ break unless tk
2265
+ case tk[:kind]
2266
+ when :on_semicolon, :on_nl, :on_ignored_nl then
2051
2267
  break if b_nest.zero?
2052
- when TkLPAREN, TkfLPAREN then
2268
+ when :on_lparen then
2053
2269
  nest += 1
2054
- when TkBEGIN then
2055
- b_nest += 1
2056
- when TkEND then
2057
- b_nest -= 1
2058
- when TkDO
2059
- break if nest.zero?
2060
- when end_token then
2061
- if end_token == TkRPAREN
2062
- nest -= 1
2063
- break if @scanner.lex_state == :EXPR_END and nest.zero?
2064
- else
2065
- break unless @scanner.continue
2270
+ when :on_rparen then
2271
+ nest -= 1
2272
+ when :on_kw then
2273
+ case tk[:text]
2274
+ when 'begin'
2275
+ b_nest += 1
2276
+ when 'end'
2277
+ b_nest -= 1
2278
+ when 'do'
2279
+ break if nest.zero?
2280
+ end
2281
+ when :on_comment, :on_embdoc then
2282
+ if b_nest.zero? and "\n" == tk[:text][-1] then
2283
+ break
2066
2284
  end
2067
- when nil then
2068
- break
2069
2285
  end
2070
2286
  tk = get_tk
2071
2287
  end
2072
2288
 
2073
- skip_tkspace false
2289
+ skip_tkspace_without_nl
2074
2290
 
2075
- get_tk if TkDO === peek_tk
2291
+ get_tk if peek_tk && :on_kw == peek_tk[:kind] && 'do' == peek_tk[:text]
2076
2292
  end
2077
2293
 
2078
2294
  ##
2079
2295
  # skip the var [in] part of a 'for' statement
2080
2296
 
2081
2297
  def skip_for_variable
2082
- skip_tkspace false
2298
+ skip_tkspace_without_nl
2083
2299
  get_tk
2084
- skip_tkspace false
2300
+ skip_tkspace_without_nl
2085
2301
  tk = get_tk
2086
- unget_tk(tk) unless TkIN === tk
2302
+ unget_tk(tk) unless :on_kw == tk[:kind] and 'in' == tk[:text]
2087
2303
  end
2088
2304
 
2089
2305
  ##
@@ -2100,8 +2316,9 @@ class RDoc::Parser::Ruby < RDoc::Parser
2100
2316
 
2101
2317
  def skip_tkspace_comment(skip_nl = true)
2102
2318
  loop do
2103
- skip_tkspace skip_nl
2104
- return unless TkCOMMENT === peek_tk
2319
+ skip_nl ? skip_tkspace : skip_tkspace_without_nl
2320
+ next_tk = peek_tk
2321
+ return if next_tk.nil? || (:on_comment != next_tk[:kind] and :on_embdoc != next_tk[:kind])
2105
2322
  get_tk
2106
2323
  end
2107
2324
  end