yard 0.9.36 → 0.9.40

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 (81) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +59 -1
  3. data/README.md +29 -25
  4. data/docs/GettingStarted.md +41 -15
  5. data/docs/Tags.md +5 -5
  6. data/docs/Templates.md +5 -4
  7. data/docs/WhatsNew.md +59 -7
  8. data/docs/templates/default/yard_tags/html/setup.rb +1 -1
  9. data/lib/yard/autoload.rb +18 -0
  10. data/lib/yard/cli/diff.rb +7 -2
  11. data/lib/yard/code_objects/base.rb +1 -1
  12. data/lib/yard/code_objects/extra_file_object.rb +1 -0
  13. data/lib/yard/code_objects/macro_object.rb +0 -1
  14. data/lib/yard/code_objects/proxy.rb +1 -1
  15. data/lib/yard/docstring_parser.rb +0 -1
  16. data/lib/yard/handlers/base.rb +23 -1
  17. data/lib/yard/handlers/processor.rb +1 -1
  18. data/lib/yard/handlers/rbs/attribute_handler.rb +43 -0
  19. data/lib/yard/handlers/rbs/base.rb +38 -0
  20. data/lib/yard/handlers/rbs/constant_handler.rb +18 -0
  21. data/lib/yard/handlers/rbs/method_handler.rb +327 -0
  22. data/lib/yard/handlers/rbs/mixin_handler.rb +20 -0
  23. data/lib/yard/handlers/rbs/namespace_handler.rb +26 -0
  24. data/lib/yard/handlers/ruby/attribute_handler.rb +7 -4
  25. data/lib/yard/handlers/ruby/constant_handler.rb +24 -6
  26. data/lib/yard/handlers/ruby/legacy/visibility_handler.rb +2 -1
  27. data/lib/yard/handlers/ruby/visibility_handler.rb +14 -1
  28. data/lib/yard/i18n/locale.rb +1 -1
  29. data/lib/yard/i18n/pot_generator.rb +1 -1
  30. data/lib/yard/logging.rb +116 -61
  31. data/lib/yard/open_struct.rb +67 -0
  32. data/lib/yard/parser/rbs/rbs_parser.rb +325 -0
  33. data/lib/yard/parser/rbs/statement.rb +75 -0
  34. data/lib/yard/parser/ruby/ast_node.rb +5 -4
  35. data/lib/yard/parser/ruby/legacy/irb/slex.rb +19 -1
  36. data/lib/yard/parser/ruby/legacy/ruby_lex.rb +20 -5
  37. data/lib/yard/parser/ruby/ruby_parser.rb +109 -24
  38. data/lib/yard/parser/source_parser.rb +5 -4
  39. data/lib/yard/registry_resolver.rb +7 -0
  40. data/lib/yard/rubygems/specification.rb +1 -1
  41. data/lib/yard/server/library_version.rb +1 -1
  42. data/lib/yard/server/templates/default/fulldoc/html/js/autocomplete.js +208 -12
  43. data/lib/yard/server/templates/default/layout/html/breadcrumb.erb +1 -17
  44. data/lib/yard/server/templates/default/method_details/html/permalink.erb +4 -2
  45. data/lib/yard/server/templates/doc_server/library_list/html/headers.erb +3 -3
  46. data/lib/yard/server/templates/doc_server/library_list/html/library_list.erb +2 -3
  47. data/lib/yard/server/templates/doc_server/processing/html/processing.erb +22 -16
  48. data/lib/yard/tags/default_factory.rb +1 -0
  49. data/lib/yard/tags/directives.rb +7 -1
  50. data/lib/yard/tags/library.rb +3 -3
  51. data/lib/yard/tags/overload_tag.rb +2 -1
  52. data/lib/yard/tags/tag.rb +2 -1
  53. data/lib/yard/tags/types_explainer.rb +5 -4
  54. data/lib/yard/templates/engine.rb +0 -1
  55. data/lib/yard/templates/helpers/base_helper.rb +1 -1
  56. data/lib/yard/templates/helpers/html_helper.rb +21 -6
  57. data/lib/yard/templates/helpers/html_syntax_highlight_helper.rb +6 -1
  58. data/lib/yard/templates/helpers/markup/hybrid_markdown.rb +2125 -0
  59. data/lib/yard/templates/helpers/markup/rdoc_markup.rb +2 -0
  60. data/lib/yard/templates/helpers/markup_helper.rb +4 -2
  61. data/lib/yard/templates/template_options.rb +0 -1
  62. data/lib/yard/version.rb +1 -1
  63. data/po/ja.po +82 -82
  64. data/templates/default/fulldoc/html/css/full_list.css +3 -3
  65. data/templates/default/fulldoc/html/css/style.css +8 -15
  66. data/templates/default/fulldoc/html/full_list.erb +8 -5
  67. data/templates/default/fulldoc/html/js/app.js +546 -281
  68. data/templates/default/fulldoc/html/js/full_list.js +315 -189
  69. data/templates/default/fulldoc/html/setup.rb +10 -2
  70. data/templates/default/layout/html/headers.erb +1 -1
  71. data/templates/default/method/html/header.erb +3 -3
  72. data/templates/default/module/html/defines.erb +3 -3
  73. data/templates/default/module/html/inherited_methods.erb +1 -0
  74. data/templates/default/module/html/method_summary.erb +8 -0
  75. data/templates/default/module/setup.rb +20 -0
  76. data/templates/default/onefile/html/headers.erb +2 -0
  77. data/templates/default/onefile/html/layout.erb +3 -4
  78. data/templates/default/tags/html/example.erb +2 -2
  79. data/templates/guide/fulldoc/html/js/app.js +57 -26
  80. data/templates/guide/layout/html/layout.erb +9 -11
  81. metadata +19 -8
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+ module YARD
3
+ module Parser
4
+ module RBS
5
+ # Represents a single parsed declaration from an RBS file.
6
+ # Each Statement may have a block of child statements for
7
+ # namespace declarations (class, module, interface).
8
+ class Statement
9
+ # @return [Symbol] declaration type:
10
+ # :class, :module, :interface, :method_def,
11
+ # :attr_reader, :attr_writer, :attr_accessor,
12
+ # :include, :extend, :prepend, :constant, :alias
13
+ attr_reader :type
14
+
15
+ # @return [String] the declaration name
16
+ attr_reader :name
17
+
18
+ # @return [String, nil] the superclass name (for :class)
19
+ attr_reader :superclass
20
+
21
+ # @return [Integer] 1-indexed line number of this statement
22
+ attr_reader :line
23
+
24
+ # @return [String] raw source text of the statement
25
+ attr_reader :source
26
+
27
+ # @return [String, nil] adjacent comment text (the docstring)
28
+ attr_reader :comments
29
+
30
+ # @return [Range, nil] line range of the preceding comments
31
+ attr_reader :comments_range
32
+
33
+ # @return [false] RBS files don't use ## hash-flag comments
34
+ attr_reader :comments_hash_flag
35
+
36
+ # @return [Array<Statement>] child statements for namespace blocks
37
+ attr_reader :block
38
+
39
+ # @return [Array<String>] RBS type signature strings for :method_def
40
+ # Each element is one overload (e.g. "(String name) -> Integer")
41
+ attr_reader :signatures
42
+
43
+ # @return [String, nil] mixin name for :include/:extend/:prepend
44
+ attr_reader :mixin_name
45
+
46
+ # @return [String, nil] RBS type annotation for attrs and constants
47
+ attr_reader :attr_rbs_type
48
+
49
+ # @return [Symbol, nil] :class or :instance scope hint from parser
50
+ attr_reader :visibility
51
+
52
+ def initialize(attrs = {})
53
+ @type = attrs[:type]
54
+ @name = attrs[:name]
55
+ @superclass = attrs[:superclass]
56
+ @line = attrs[:line] || 1
57
+ @source = attrs[:source] || ''
58
+ @comments = attrs[:comments]
59
+ @comments_range = attrs[:comments_range]
60
+ @comments_hash_flag = false
61
+ @block = attrs[:block] || []
62
+ @signatures = attrs[:signatures] || []
63
+ @mixin_name = attrs[:mixin_name]
64
+ @attr_rbs_type = attrs[:attr_rbs_type]
65
+ @visibility = attrs[:visibility]
66
+ end
67
+
68
+ # @return [String] a textual snippet used in error messages
69
+ def show
70
+ source
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -271,7 +271,7 @@ module YARD
271
271
 
272
272
  # @return [Fixnum] the starting line number of the node
273
273
  def line
274
- line_range && line_range.first
274
+ line_range && (line_range.begin || line_range.end)
275
275
  end
276
276
 
277
277
  # @return [String] the first line of source represented by the node.
@@ -345,8 +345,8 @@ module YARD
345
345
  elsif !children.empty?
346
346
  f = children.first
347
347
  l = children.last
348
- self.line_range = Range.new(f.line_range.first, l.line_range.last)
349
- self.source_range = Range.new(f.source_range.first, l.source_range.last)
348
+ self.line_range = Range.new(f.line_range.begin, l.line_range.end)
349
+ self.source_range = Range.new(f.source_range.begin, l.source_range.end)
350
350
  elsif @fallback_line || @fallback_source
351
351
  self.line_range = @fallback_line
352
352
  self.source_range = @fallback_source
@@ -431,7 +431,8 @@ module YARD
431
431
  # shape is (required, optional, rest, more, keyword, keyword_rest, block)
432
432
  # Ruby 3.1 moves :args_forward from rest to keyword_rest
433
433
  args_index = YARD.ruby31? ? -2 : 2
434
- self[args_index].type == :args_forward if self[args_index]
434
+ node = self[args_index]
435
+ node.is_a?(AstNode) && node.type == :args_forward
435
436
  end
436
437
  end
437
438
 
@@ -10,7 +10,25 @@
10
10
  #
11
11
  #
12
12
 
13
- require "irb/notifier"
13
+ begin
14
+ require "irb/notifier"
15
+ rescue LoadError
16
+ module IRB
17
+ module DebugLogger
18
+ def self.pp(*args) end
19
+ end
20
+
21
+ module Notifier
22
+ D_NOMSG = 0x00
23
+ def self.def_notifier(*args) self end
24
+ def self.pp(*args) end
25
+ def self.exec_if(*args, &block) end
26
+ def self.printf(*args) end
27
+ def self.puts(*args) end
28
+ def self.level=(value) end
29
+ end
30
+ end
31
+ end
14
32
 
15
33
  # @private
16
34
  module IRB
@@ -656,7 +656,7 @@ module YARD
656
656
  if @lex_state != EXPR_END && @lex_state != EXPR_CLASS &&
657
657
  (@lex_state != EXPR_ARG || @space_seen)
658
658
  c = peek(0)
659
- tk = identify_here_document if /[-\w\"\'\`]/ =~ c
659
+ tk = identify_here_document if /[-~\w\"\'\`]/ =~ c
660
660
  end
661
661
  if !tk
662
662
  @lex_state = EXPR_BEG
@@ -978,7 +978,7 @@ module YARD
978
978
  end
979
979
 
980
980
  def identify_identifier
981
- token = ""
981
+ token = String.new
982
982
  token.concat getc if peek(0) =~ /[$@]/
983
983
  token.concat getc if peek(0) == "@"
984
984
 
@@ -1063,6 +1063,8 @@ module YARD
1063
1063
  ch = getc
1064
1064
  if ch == "-"
1065
1065
  ch = getc
1066
+ elsif ch == "~"
1067
+ ch = getc
1066
1068
  indent = true
1067
1069
  end
1068
1070
  if /['"`]/ =~ ch # '
@@ -1096,9 +1098,12 @@ module YARD
1096
1098
  str = String.new
1097
1099
  while (l = gets)
1098
1100
  l.chomp!
1099
- l.strip! if indent
1100
- break if l == quoted
1101
- str << l.chomp << "\n"
1101
+ if l == quoted
1102
+ str = dedent(str) if indent
1103
+ break
1104
+ else
1105
+ str << l.chomp << "\n"
1106
+ end
1102
1107
  end
1103
1108
 
1104
1109
  @reader.divert_read_from(reserve)
@@ -1108,6 +1113,16 @@ module YARD
1108
1113
  Token(Ltype2Token[lt], str).set_text(str.dump)
1109
1114
  end
1110
1115
 
1116
+ def dedent(str)
1117
+ lines = str.split("\n", -1)
1118
+ dedent_amt = lines.map do |line|
1119
+ line =~ /\S/ ? line.match(/^ */).offset(0)[1] : nil
1120
+ end.compact.min || 0
1121
+ return str if dedent_amt.zero?
1122
+
1123
+ lines.map { |line| line =~ /\S/ ? line.gsub(/^ {#{dedent_amt}}/, "") : line }.join("\n")
1124
+ end
1125
+
1111
1126
  def identify_quotation(initial_char)
1112
1127
  ch = getc
1113
1128
  if lt = PERCENT_LTYPE[ch]
@@ -236,14 +236,26 @@ module YARD
236
236
 
237
237
  def visit_event(node)
238
238
  map = @map[MAPPINGS[node.type]]
239
- lstart, sstart = *(map ? map.pop : [lineno, @ns_charno - 1])
239
+
240
+ # Pattern matching and `in` syntax creates :case nodes without 'case' tokens,
241
+ # fall back to the first child node.
242
+ if node.type == :case && (!map || map.empty?) && (child_node = node[0])
243
+ lstart = child_node.line_range.first
244
+ sstart = child_node.source_range.first
245
+ else
246
+ lstart, sstart = *(map ? map.pop : [lineno, @ns_charno - 1])
247
+ (@map[:rbrace] ||= []).shift if map && MAPPINGS[node.type] == :lbrace
248
+ end
249
+
250
+ raise "Cannot determine start of node #{node} around #{file}:#{lineno}" if lstart.nil? || sstart.nil?
251
+
240
252
  node.source_range = Range.new(sstart, @ns_charno - 1)
241
253
  node.line_range = Range.new(lstart, lineno)
242
254
  if node.respond_to?(:block)
243
255
  sr = node.block.source_range
244
256
  lr = node.block.line_range
245
- node.block.source_range = Range.new(sr.first, @tokens.last[2][1] - 1)
246
- node.block.line_range = Range.new(lr.first, @tokens.last[2][0])
257
+ node.block.source_range = Range.new(sr.begin, @tokens.last[2][1] - 1)
258
+ node.block.line_range = Range.new(lr.begin, @tokens.last[2][0])
247
259
  end
248
260
  node
249
261
  end
@@ -259,7 +271,10 @@ module YARD
259
271
  def visit_ns_token(token, data, ast_token = false)
260
272
  add_token(token, data)
261
273
  ch = charno
262
- @last_ns_token = [token, data]
274
+
275
+ # For purposes of tracking parsing state, don't treat keywords as such
276
+ # where used as a symbol identifier.
277
+ @last_ns_token = [@last_ns_token && @last_ns_token.first == :symbeg ? :symbol : token, data]
263
278
  @charno += data.length
264
279
  @ns_charno = charno
265
280
  @newline = [:semicolon, :comment, :kw, :op, :lparen, :lbrace].include?(token)
@@ -272,14 +287,14 @@ module YARD
272
287
  if @percent_ary
273
288
  if token == :words_sep && data !~ /\s\z/
274
289
  rng = @percent_ary.source_range
275
- rng = Range.new(rng.first, rng.last + data.length)
290
+ rng = Range.new(rng.begin, rng.end.to_i + data.length)
276
291
  @percent_ary.source_range = rng
277
292
  @tokens << [token, data, [lineno, charno]]
278
293
  @percent_ary = nil
279
294
  return
280
295
  elsif token == :tstring_end && data =~ /\A\s/
281
296
  rng = @percent_ary.source_range
282
- rng = Range.new(rng.first, rng.last + data.length)
297
+ rng = Range.new(rng.begin, rng.end.to_i + data.length)
283
298
  @percent_ary.source_range = rng
284
299
  @tokens << [token, data, [lineno, charno]]
285
300
  @percent_ary = nil
@@ -294,7 +309,7 @@ module YARD
294
309
  @heredoc_tokens << [token, data, [lineno, charno]]
295
310
 
296
311
  # fix ripper encoding of heredoc bug
297
- # (see http://bugs.ruby-lang.org/issues/6200)
312
+ # (see https://bugs.ruby-lang.org/issues/6200)
298
313
  data.force_encoding(file_encoding) if file_encoding
299
314
 
300
315
  @heredoc_state = :ended if token == :heredoc_end
@@ -322,6 +337,7 @@ module YARD
322
337
  undef on_aref_field
323
338
  undef on_lbracket
324
339
  undef on_rbracket
340
+ undef on_rbrace
325
341
  undef on_string_literal
326
342
  undef on_lambda
327
343
  undef on_unary
@@ -357,6 +373,20 @@ module YARD
357
373
  visit_event AstNode.new(:hash, args.first || [])
358
374
  end
359
375
 
376
+ # Ruby 3.0+ pattern matching: braced hash patterns ({key: val} syntax) fire
377
+ # on_lbrace and on_rbrace scanner events. The corresponding parser event is
378
+ # on_hshptn (not on_hash), so we must clean up the brace maps to prevent stale
379
+ # entries from corrupting source ranges of later hash literals and brace blocks.
380
+ # Bare hash patterns (key: val without braces) fire no brace scanner events, so
381
+ # we only clean up when @map[:rbrace] confirms a closing brace was scanned.
382
+ def on_hshptn(*args)
383
+ if (@map[:rbrace] ||= []).any?
384
+ (@map[:lbrace] ||= []).pop
385
+ @map[:rbrace].shift
386
+ end
387
+ AstNode.new(:hshptn, args)
388
+ end
389
+
360
390
  def on_bare_assoc_hash(*args)
361
391
  AstNode.new(:list, args.first)
362
392
  end
@@ -377,20 +407,22 @@ module YARD
377
407
  def on_aref(*args)
378
408
  @map[:lbracket].pop
379
409
  ll, lc = *@map[:aref].shift
380
- sr = args.first.source_range.first..lc
381
- lr = args.first.line_range.first..ll
410
+ sr = args.first.source_range.begin..lc
411
+ lr = args.first.line_range.begin..ll
382
412
  AstNode.new(:aref, args, :char => sr, :line => lr)
383
413
  end
384
414
 
385
415
  def on_aref_field(*args)
386
416
  @map[:lbracket].pop
387
- AstNode.new(:aref_field, args,
388
- :listline => lineno..lineno, :listchar => charno...charno)
417
+ ll, lc = *@map[:aref].shift
418
+ sr = args.first.source_range.begin..lc
419
+ lr = args.first.line_range.begin..ll
420
+ AstNode.new(:aref_field, args, :char => sr, :line => lr)
389
421
  end
390
422
 
391
423
  def on_array(other)
392
424
  node = AstNode.node_class_for(:array).new(:array, [other])
393
- map = @map[MAPPINGS[node.type]]
425
+ map = @map[MAPPINGS[node.type]] if other.nil? || other.type == :list
394
426
  if map && !map.empty?
395
427
  lstart, sstart = *map.pop
396
428
  node.source_range = Range.new(sstart, @ns_charno - 1)
@@ -406,6 +438,27 @@ module YARD
406
438
  node
407
439
  end
408
440
 
441
+ # Ruby 3.0+ pattern matching: array patterns (SomeClass[a, b]) and find patterns
442
+ # (SomeClass[*pre, val, *post]) use [...] brackets, which fire on_lbracket and
443
+ # on_rbracket scanner events. The corresponding parser events are on_aryptn/on_fndptn
444
+ # (not on_aref), so we must clean up the bracket maps to prevent stale entries from
445
+ # corrupting source ranges of later array indexing expressions.
446
+ def on_aryptn(*args)
447
+ (@map[:lbracket] ||= []).pop
448
+ (@map[:aref] ||= []).shift
449
+ # Source range is intentionally not set; no handler is registered for
450
+ # pattern-match nodes, so they produce no documentation output.
451
+ AstNode.new(:aryptn, args)
452
+ end
453
+
454
+ def on_fndptn(*args)
455
+ (@map[:lbracket] ||= []).pop
456
+ (@map[:aref] ||= []).shift
457
+ # Source range is intentionally not set; no handler is registered for
458
+ # pattern-match nodes, so they produce no documentation output.
459
+ AstNode.new(:fndptn, args)
460
+ end
461
+
409
462
  def on_lbracket(tok)
410
463
  (@map[:lbracket] ||= []) << [lineno, charno]
411
464
  visit_ns_token(:lbracket, tok, false)
@@ -416,6 +469,13 @@ module YARD
416
469
  visit_ns_token(:rbracket, tok, false)
417
470
  end
418
471
 
472
+ # Maintained explicitly (unlike on_lbracket/on_rbracket) so on_hshptn can
473
+ # distinguish braced from bare hash patterns in Ruby 3.0+ pattern matching.
474
+ def on_rbrace(tok)
475
+ (@map[:rbrace] ||= []) << [lineno, charno]
476
+ visit_ns_token(:rbrace, tok, false)
477
+ end
478
+
419
479
  def on_dyna_symbol(sym)
420
480
  rng = if sym.source_range.to_a.size == 0 # rubocop:disable Style/ZeroLengthPredicate
421
481
  (sym.source_range.begin - 3)...sym.source_range.end
@@ -449,8 +509,8 @@ module YARD
449
509
  def on_#{kw}(*args)
450
510
  mapping = @map[#{kw.to_s.sub(/_mod$/, '').inspect}]
451
511
  mapping.pop if mapping
452
- sr = args.last.source_range.first..args.first.source_range.last
453
- lr = args.last.line_range.first..args.first.line_range.last
512
+ sr = args.last.source_range.begin..args.first.source_range.end
513
+ lr = args.last.line_range.begin..args.first.line_range.end
454
514
  #{node_class}.new(:#{kw}, args, :line => lr, :char => sr)
455
515
  end
456
516
  eof
@@ -473,8 +533,8 @@ module YARD
473
533
  begin; undef on_#{kw}_add; rescue NameError; end
474
534
  def on_#{kw}_add(list, item)
475
535
  last = @source[@ns_charno,1] == "\n" ? @ns_charno - 1 : @ns_charno
476
- list.source_range = (list.source_range.first..last)
477
- list.line_range = (list.line_range.first..lineno)
536
+ list.source_range = (list.source_range.begin..last)
537
+ list.line_range = (list.line_range.begin..lineno)
478
538
  list.push(item)
479
539
  list
480
540
  end
@@ -485,9 +545,9 @@ module YARD
485
545
  node = visit_event_arr(LiteralNode.new(:string_literal, args))
486
546
  if args.size == 1
487
547
  r = args[0].source_range
488
- if node.source_range != Range.new(r.first - 1, r.last + 1)
548
+ if node.source_range != Range.new(r.begin - 1, r.end + 1)
489
549
  klass = AstNode.node_class_for(node[0].type)
490
- r = Range.new(node.source_range.first + 1, node.source_range.last - 1)
550
+ r = Range.new(node.source_range.begin + 1, node.source_range.end - 1)
491
551
  node[0] = klass.new(node[0].type, [@source[r]], :line => node.line_range, :char => r)
492
552
  end
493
553
  end
@@ -573,7 +633,7 @@ module YARD
573
633
  @comments_flags[lineno] = @comments_flags[lineno - 1]
574
634
  @comments_flags.delete(lineno - 1)
575
635
  range = @comments_range.delete(lineno - 1)
576
- source_range = range.first..source_range.last
636
+ source_range = range.begin..source_range.end
577
637
  comment = append_comment + "\n" + comment
578
638
  end
579
639
 
@@ -609,6 +669,7 @@ module YARD
609
669
  alias compile_error on_parse_error
610
670
 
611
671
  def comment_starts_line?(charno)
672
+ return true if @source[charno] == "\n"
612
673
  (charno - 1).downto(0) do |i|
613
674
  ch = @source[i]
614
675
  break if ch == "\n"
@@ -627,11 +688,13 @@ module YARD
627
688
  end
628
689
 
629
690
  # check upwards from line before node; check node's line at the end
630
- ((node.line - 1).downto(node.line - 2).to_a + [node.line]).each do |line|
631
- comment = @comments[line]
632
- if comment && !comment.empty?
633
- add_comment(line, node)
634
- break
691
+ if (n_l = node.line)
692
+ ((n_l - 1).downto(n_l - 2).to_a + [n_l]).each do |line|
693
+ comment = @comments[line]
694
+ if comment && !comment.empty?
695
+ add_comment(line, node)
696
+ break
697
+ end
635
698
  end
636
699
  end
637
700
 
@@ -656,6 +719,23 @@ module YARD
656
719
  end
657
720
  end unless @comments.empty?
658
721
 
722
+ # Attach comments that fall within an otherwise empty
723
+ # class or module body. Without this step, a comment used
724
+ # solely for directives (like @!method) would be treated as
725
+ # a top-level comment and its directives would not be scoped
726
+ # to the namespace.
727
+ unless @comments.empty?
728
+ root.traverse do |node|
729
+ next unless [:class, :module, :sclass].include?(node.type)
730
+ body = node.children.last
731
+ next unless body && body.type == :list && body.empty?
732
+ @comments.keys.each do |line|
733
+ next unless node.line_range.include?(line)
734
+ add_comment(line, nil, body, true)
735
+ end
736
+ end
737
+ end
738
+
659
739
  # insert all remaining comments
660
740
  @comments.each do |line, _comment|
661
741
  add_comment(line, nil, root, true)
@@ -667,6 +747,11 @@ module YARD
667
747
  def add_comment(line, node = nil, before_node = nil, into = false)
668
748
  comment = @comments[line]
669
749
  source_range = @comments_range[line]
750
+ if comment && source_range
751
+ source = @source[source_range]
752
+ last_line = source.lines.to_a.last
753
+ return if last_line && last_line =~ /^\s*\#-\s*$/
754
+ end
670
755
  line_range = ((line - comment.count("\n"))..line)
671
756
  if node.nil?
672
757
  node = CommentNode.new(:comment, [comment], :line => line_range, :char => source_range)
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  require 'stringio'
3
- require 'ostruct'
4
3
 
5
4
  module YARD
6
5
  module Parser
@@ -68,7 +67,7 @@ module YARD
68
67
 
69
68
  # The default glob of files to be parsed.
70
69
  # @since 0.9.0
71
- DEFAULT_PATH_GLOB = ["{lib,app}/**/*.rb", "ext/**/*.{c,cc,cxx,cpp,rb}"]
70
+ DEFAULT_PATH_GLOB = ["{lib,app}/**/*.{rb,rbs}", "sig/**/*.rbs", "ext/**/*.{c,cc,cxx,cpp,rb}"]
72
71
 
73
72
  # Byte order marks for various encodings
74
73
  # @since 0.7.0
@@ -106,9 +105,10 @@ module YARD
106
105
  end
107
106
  end
108
107
  files = [paths].flatten.
109
- map {|p| File.directory?(p) ? "#{p}/**/*.{rb,c,cc,cxx,cpp}" : p }.
108
+ map {|p| File.directory?(p) ? "#{p}/**/*.{rb,rbs,c,cc,cxx,cpp}" : p }.
110
109
  map {|p| p.include?("*") ? Dir[p].sort_by {|d| [d.length, d] } : p }.flatten.
111
- reject {|p| !File.file?(p) || excluded.any? {|re| p =~ re } }
110
+ reject {|p| !File.file?(p) || excluded.any? {|re| p =~ re } }.
111
+ map {|p| p.encoding == Encoding.default_external ? p : p.dup.force_encoding(Encoding.default_external) }
112
112
 
113
113
  log.enter_level(level) do
114
114
  parse_in_order(*files.uniq)
@@ -379,6 +379,7 @@ module YARD
379
379
  register_parser_type :ruby, Ruby::RubyParser
380
380
  register_parser_type :ruby18, Ruby::Legacy::RubyParser
381
381
  register_parser_type :c, C::CParser, ['c', 'cc', 'cxx', 'cpp']
382
+ register_parser_type :rbs, RBS::RbsParser, ['rbs']
382
383
 
383
384
  self.parser_type = :ruby
384
385
 
@@ -75,6 +75,13 @@ module YARD
75
75
  lexical_lookup = 0
76
76
  while namespace && !resolved
77
77
  resolved = lookup_path_direct(namespace, path, type)
78
+ # Prevent a bare name from resolving back to the namespace we started
79
+ # from when searching through a parent namespace. For example,
80
+ # `include Enumerable` inside `A::Enumerable` would walk up to namespace
81
+ # `A` and match `A::Enumerable`, creating a false self-referential mixin.
82
+ # Only skip when we have already moved to a parent (namespace != orignamespace).
83
+ # See https://github.com/lsegal/yard/issues/1116
84
+ resolved = nil if resolved.equal?(orignamespace) && !namespace.equal?(orignamespace)
78
85
  resolved ||= lookup_path_inherited(namespace, path, type) if inheritance
79
86
  break if resolved
80
87
  namespace = namespace.parent
@@ -11,7 +11,7 @@ class Gem::Specification
11
11
  @has_rdoc == 'yard'
12
12
  end
13
13
 
14
- undef has_rdoc?
14
+ undef has_rdoc? if method_defined?(:has_rdoc?)
15
15
  def has_rdoc?
16
16
  (@has_rdoc ||= true) && @has_rdoc != 'yard'
17
17
  end
@@ -71,7 +71,7 @@ module YARD
71
71
  # def load_yardoc_from_http
72
72
  # Thread.new do
73
73
  # # zip/unzip method implementations are not shown
74
- # download_zip_file("http://mysite.com/yardocs/#{self}.zip")
74
+ # download_zip_file("https://mysite.com/yardocs/#{self}.zip")
75
75
  # unzip_file_to("/path/to/yardocs/#{self}")
76
76
  # end
77
77
  #