yard 0.9.28 → 0.9.43
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +139 -1
- data/LEGAL +29 -1
- data/README.md +29 -25
- data/docs/GettingStarted.md +41 -15
- data/docs/Parser.md +17 -42
- data/docs/Tags.md +6 -6
- data/docs/Templates.md +5 -4
- data/docs/WhatsNew.md +61 -9
- data/docs/templates/default/yard_tags/html/setup.rb +1 -1
- data/lib/yard/autoload.rb +20 -1
- data/lib/yard/cli/command.rb +1 -1
- data/lib/yard/cli/diff.rb +7 -2
- data/lib/yard/cli/yardoc.rb +1 -1
- data/lib/yard/code_objects/base.rb +6 -2
- data/lib/yard/code_objects/extra_file_object.rb +1 -0
- data/lib/yard/code_objects/macro_object.rb +0 -1
- data/lib/yard/code_objects/proxy.rb +1 -1
- data/lib/yard/docstring_parser.rb +1 -2
- data/lib/yard/handlers/base.rb +23 -1
- data/lib/yard/handlers/processor.rb +1 -1
- data/lib/yard/handlers/rbs/attribute_handler.rb +79 -0
- data/lib/yard/handlers/rbs/base.rb +38 -0
- data/lib/yard/handlers/rbs/constant_handler.rb +18 -0
- data/lib/yard/handlers/rbs/method_handler.rb +327 -0
- data/lib/yard/handlers/rbs/mixin_handler.rb +20 -0
- data/lib/yard/handlers/rbs/namespace_handler.rb +26 -0
- data/lib/yard/handlers/ruby/attribute_handler.rb +7 -4
- data/lib/yard/handlers/ruby/constant_handler.rb +24 -6
- data/lib/yard/handlers/ruby/legacy/attribute_handler.rb +1 -1
- data/lib/yard/handlers/ruby/legacy/visibility_handler.rb +2 -1
- data/lib/yard/handlers/ruby/mixin_handler.rb +13 -6
- data/lib/yard/handlers/ruby/visibility_handler.rb +14 -1
- data/lib/yard/i18n/locale.rb +2 -2
- data/lib/yard/i18n/message.rb +2 -2
- data/lib/yard/i18n/messages.rb +1 -1
- data/lib/yard/i18n/pot_generator.rb +2 -2
- data/lib/yard/logging.rb +116 -61
- data/lib/yard/open_struct.rb +67 -0
- data/lib/yard/options.rb +1 -1
- data/lib/yard/parser/rbs/rbs_parser.rb +325 -0
- data/lib/yard/parser/rbs/statement.rb +75 -0
- data/lib/yard/parser/ruby/ast_node.rb +5 -4
- data/lib/yard/parser/ruby/legacy/irb/slex.rb +19 -1
- data/lib/yard/parser/ruby/legacy/ruby_lex.rb +20 -5
- data/lib/yard/parser/ruby/ruby_parser.rb +117 -26
- data/lib/yard/parser/source_parser.rb +7 -7
- data/lib/yard/registry_resolver.rb +9 -1
- data/lib/yard/rubygems/specification.rb +1 -1
- data/lib/yard/server/commands/base.rb +2 -2
- data/lib/yard/server/commands/library_command.rb +8 -8
- data/lib/yard/server/commands/static_file_helpers.rb +1 -2
- data/lib/yard/server/http_utils.rb +512 -0
- data/lib/yard/server/library_version.rb +1 -1
- data/lib/yard/server/rack_adapter.rb +13 -5
- data/lib/yard/server/templates/default/fulldoc/html/css/custom.css +168 -88
- data/lib/yard/server/templates/default/fulldoc/html/js/autocomplete.js +203 -12
- data/lib/yard/server/templates/default/layout/html/breadcrumb.erb +1 -17
- data/lib/yard/server/templates/default/method_details/html/permalink.erb +4 -2
- data/lib/yard/server/templates/doc_server/library_list/html/headers.erb +3 -3
- data/lib/yard/server/templates/doc_server/library_list/html/library_list.erb +2 -3
- data/lib/yard/server/templates/doc_server/processing/html/processing.erb +22 -16
- data/lib/yard/tags/default_factory.rb +1 -0
- data/lib/yard/tags/directives.rb +7 -1
- data/lib/yard/tags/library.rb +3 -3
- data/lib/yard/tags/overload_tag.rb +2 -1
- data/lib/yard/tags/tag.rb +4 -3
- data/lib/yard/tags/types_explainer.rb +6 -5
- data/lib/yard/templates/engine.rb +0 -1
- data/lib/yard/templates/helpers/base_helper.rb +1 -1
- data/lib/yard/templates/helpers/html_helper.rb +21 -6
- data/lib/yard/templates/helpers/html_syntax_highlight_helper.rb +6 -1
- data/lib/yard/templates/helpers/markup/hybrid_markdown.rb +2147 -0
- data/lib/yard/templates/helpers/markup/rdoc_markup.rb +2 -0
- data/lib/yard/templates/helpers/markup_helper.rb +4 -2
- data/lib/yard/templates/template_options.rb +0 -1
- data/lib/yard/version.rb +1 -1
- data/po/ja.po +101 -101
- data/templates/default/fulldoc/html/css/common.css +1 -1
- data/templates/default/fulldoc/html/css/full_list.css +201 -53
- data/templates/default/fulldoc/html/css/style.css +991 -399
- data/templates/default/fulldoc/html/frames.erb +9 -4
- data/templates/default/fulldoc/html/full_list.erb +8 -5
- data/templates/default/fulldoc/html/js/app.js +799 -312
- data/templates/default/fulldoc/html/js/full_list.js +332 -214
- data/templates/default/fulldoc/html/setup.rb +10 -2
- data/templates/default/layout/html/headers.erb +1 -1
- data/templates/default/layout/html/layout.erb +3 -1
- data/templates/default/method/html/header.erb +3 -3
- data/templates/default/module/html/defines.erb +3 -3
- data/templates/default/module/html/inherited_methods.erb +1 -0
- data/templates/default/module/html/method_summary.erb +8 -0
- data/templates/default/module/setup.rb +20 -0
- data/templates/default/onefile/html/headers.erb +2 -0
- data/templates/default/onefile/html/layout.erb +3 -4
- data/templates/default/tags/html/example.erb +2 -2
- data/templates/default/tags/html/option.erb +1 -1
- data/templates/guide/fulldoc/html/css/style.css +347 -97
- data/templates/guide/fulldoc/html/js/app.js +61 -33
- data/templates/guide/layout/html/layout.erb +69 -72
- metadata +21 -60
- data/.dockerignore +0 -2
- data/.gitattributes +0 -4
- data/.github/FUNDING.yml +0 -3
- data/.github/ISSUE_TEMPLATE.md +0 -33
- data/.github/PULL_REQUEST_TEMPLATE.md +0 -12
- data/.github/workflows/ci.yml +0 -30
- data/.github/workflows/gem.yml +0 -19
- data/.gitignore +0 -14
- data/.rspec +0 -2
- data/.rubocop.yml +0 -112
- data/CODE_OF_CONDUCT.md +0 -15
- data/CONTRIBUTING.md +0 -140
- data/Dockerfile.samus +0 -28
- data/Gemfile +0 -34
- data/Rakefile +0 -36
- data/SECURITY.md +0 -26
- data/benchmarks/builtins_vs_eval.rb +0 -24
- data/benchmarks/concat_vs_join.rb +0 -13
- data/benchmarks/erb_vs_erubis.rb +0 -54
- data/benchmarks/format_args.rb +0 -47
- data/benchmarks/generation.rb +0 -38
- data/benchmarks/marshal_vs_dbm.rb +0 -64
- data/benchmarks/parsing.rb +0 -46
- data/benchmarks/pathname_vs_string.rb +0 -51
- data/benchmarks/rdoc_vs_yardoc.rb +0 -11
- data/benchmarks/registry_store_types.rb +0 -49
- data/benchmarks/ri_vs_yri.rb +0 -19
- data/benchmarks/ripper_parser.rb +0 -13
- data/benchmarks/splat_vs_flatten.rb +0 -13
- data/benchmarks/template_erb.rb +0 -23
- data/benchmarks/template_format.rb +0 -7
- data/benchmarks/template_profile.rb +0 -18
- data/benchmarks/yri_cache.rb +0 -20
- data/samus.json +0 -49
- data/tasks/prepare_tag.rake +0 -45
- data/tasks/update_error_map.rake +0 -53
- data/yard.gemspec +0 -25
|
@@ -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.
|
|
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.
|
|
349
|
-
self.source_range = Range.new(f.source_range.
|
|
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
|
-
|
|
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
|
-
|
|
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 /[
|
|
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
|
|
1100
|
-
|
|
1101
|
-
|
|
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]
|
|
@@ -133,6 +133,12 @@ module YARD
|
|
|
133
133
|
AST_TOKENS = [:CHAR, :backref, :const, :cvar, :gvar, :heredoc_end, :ident,
|
|
134
134
|
:int, :float, :ivar, :label, :period, :regexp_end, :tstring_content, :backtick]
|
|
135
135
|
|
|
136
|
+
COMMENT_SKIP_NODE_TYPES = [
|
|
137
|
+
:comment,
|
|
138
|
+
:void_stmt,
|
|
139
|
+
:list
|
|
140
|
+
].freeze
|
|
141
|
+
|
|
136
142
|
MAPPINGS.each do |k, v|
|
|
137
143
|
if Array === v
|
|
138
144
|
v.each {|vv| (REV_MAPPINGS[vv] ||= []) << k }
|
|
@@ -144,7 +150,7 @@ module YARD
|
|
|
144
150
|
PARSER_EVENT_TABLE.each do |event, arity|
|
|
145
151
|
node_class = AstNode.node_class_for(event)
|
|
146
152
|
|
|
147
|
-
if /_new\z/ =~ event.to_s
|
|
153
|
+
if arity == 0 && /_new\z/ =~ event.to_s
|
|
148
154
|
module_eval(<<-eof, __FILE__, __LINE__ + 1)
|
|
149
155
|
def on_#{event}(*args)
|
|
150
156
|
#{node_class}.new(:list, args, :listchar => charno...charno, :listline => lineno..lineno)
|
|
@@ -230,14 +236,26 @@ module YARD
|
|
|
230
236
|
|
|
231
237
|
def visit_event(node)
|
|
232
238
|
map = @map[MAPPINGS[node.type]]
|
|
233
|
-
|
|
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
|
+
|
|
234
252
|
node.source_range = Range.new(sstart, @ns_charno - 1)
|
|
235
253
|
node.line_range = Range.new(lstart, lineno)
|
|
236
254
|
if node.respond_to?(:block)
|
|
237
255
|
sr = node.block.source_range
|
|
238
256
|
lr = node.block.line_range
|
|
239
|
-
node.block.source_range = Range.new(sr.
|
|
240
|
-
node.block.line_range = Range.new(lr.
|
|
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])
|
|
241
259
|
end
|
|
242
260
|
node
|
|
243
261
|
end
|
|
@@ -253,7 +271,10 @@ module YARD
|
|
|
253
271
|
def visit_ns_token(token, data, ast_token = false)
|
|
254
272
|
add_token(token, data)
|
|
255
273
|
ch = charno
|
|
256
|
-
|
|
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]
|
|
257
278
|
@charno += data.length
|
|
258
279
|
@ns_charno = charno
|
|
259
280
|
@newline = [:semicolon, :comment, :kw, :op, :lparen, :lbrace].include?(token)
|
|
@@ -266,14 +287,14 @@ module YARD
|
|
|
266
287
|
if @percent_ary
|
|
267
288
|
if token == :words_sep && data !~ /\s\z/
|
|
268
289
|
rng = @percent_ary.source_range
|
|
269
|
-
rng = Range.new(rng.
|
|
290
|
+
rng = Range.new(rng.begin, rng.end.to_i + data.length)
|
|
270
291
|
@percent_ary.source_range = rng
|
|
271
292
|
@tokens << [token, data, [lineno, charno]]
|
|
272
293
|
@percent_ary = nil
|
|
273
294
|
return
|
|
274
295
|
elsif token == :tstring_end && data =~ /\A\s/
|
|
275
296
|
rng = @percent_ary.source_range
|
|
276
|
-
rng = Range.new(rng.
|
|
297
|
+
rng = Range.new(rng.begin, rng.end.to_i + data.length)
|
|
277
298
|
@percent_ary.source_range = rng
|
|
278
299
|
@tokens << [token, data, [lineno, charno]]
|
|
279
300
|
@percent_ary = nil
|
|
@@ -288,7 +309,7 @@ module YARD
|
|
|
288
309
|
@heredoc_tokens << [token, data, [lineno, charno]]
|
|
289
310
|
|
|
290
311
|
# fix ripper encoding of heredoc bug
|
|
291
|
-
# (see
|
|
312
|
+
# (see https://bugs.ruby-lang.org/issues/6200)
|
|
292
313
|
data.force_encoding(file_encoding) if file_encoding
|
|
293
314
|
|
|
294
315
|
@heredoc_state = :ended if token == :heredoc_end
|
|
@@ -316,6 +337,7 @@ module YARD
|
|
|
316
337
|
undef on_aref_field
|
|
317
338
|
undef on_lbracket
|
|
318
339
|
undef on_rbracket
|
|
340
|
+
undef on_rbrace
|
|
319
341
|
undef on_string_literal
|
|
320
342
|
undef on_lambda
|
|
321
343
|
undef on_unary
|
|
@@ -351,6 +373,20 @@ module YARD
|
|
|
351
373
|
visit_event AstNode.new(:hash, args.first || [])
|
|
352
374
|
end
|
|
353
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
|
+
|
|
354
390
|
def on_bare_assoc_hash(*args)
|
|
355
391
|
AstNode.new(:list, args.first)
|
|
356
392
|
end
|
|
@@ -371,20 +407,22 @@ module YARD
|
|
|
371
407
|
def on_aref(*args)
|
|
372
408
|
@map[:lbracket].pop
|
|
373
409
|
ll, lc = *@map[:aref].shift
|
|
374
|
-
sr = args.first.source_range.
|
|
375
|
-
lr = args.first.line_range.
|
|
410
|
+
sr = args.first.source_range.begin..lc
|
|
411
|
+
lr = args.first.line_range.begin..ll
|
|
376
412
|
AstNode.new(:aref, args, :char => sr, :line => lr)
|
|
377
413
|
end
|
|
378
414
|
|
|
379
415
|
def on_aref_field(*args)
|
|
380
416
|
@map[:lbracket].pop
|
|
381
|
-
|
|
382
|
-
|
|
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)
|
|
383
421
|
end
|
|
384
422
|
|
|
385
423
|
def on_array(other)
|
|
386
424
|
node = AstNode.node_class_for(:array).new(:array, [other])
|
|
387
|
-
map = @map[MAPPINGS[node.type]]
|
|
425
|
+
map = @map[MAPPINGS[node.type]] if other.nil? || other.type == :list
|
|
388
426
|
if map && !map.empty?
|
|
389
427
|
lstart, sstart = *map.pop
|
|
390
428
|
node.source_range = Range.new(sstart, @ns_charno - 1)
|
|
@@ -400,6 +438,27 @@ module YARD
|
|
|
400
438
|
node
|
|
401
439
|
end
|
|
402
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
|
+
|
|
403
462
|
def on_lbracket(tok)
|
|
404
463
|
(@map[:lbracket] ||= []) << [lineno, charno]
|
|
405
464
|
visit_ns_token(:lbracket, tok, false)
|
|
@@ -410,6 +469,13 @@ module YARD
|
|
|
410
469
|
visit_ns_token(:rbracket, tok, false)
|
|
411
470
|
end
|
|
412
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
|
+
|
|
413
479
|
def on_dyna_symbol(sym)
|
|
414
480
|
rng = if sym.source_range.to_a.size == 0 # rubocop:disable Style/ZeroLengthPredicate
|
|
415
481
|
(sym.source_range.begin - 3)...sym.source_range.end
|
|
@@ -443,8 +509,8 @@ module YARD
|
|
|
443
509
|
def on_#{kw}(*args)
|
|
444
510
|
mapping = @map[#{kw.to_s.sub(/_mod$/, '').inspect}]
|
|
445
511
|
mapping.pop if mapping
|
|
446
|
-
sr = args.last.source_range.
|
|
447
|
-
lr = args.last.line_range.
|
|
512
|
+
sr = args.last.source_range.begin..args.first.source_range.end
|
|
513
|
+
lr = args.last.line_range.begin..args.first.line_range.end
|
|
448
514
|
#{node_class}.new(:#{kw}, args, :line => lr, :char => sr)
|
|
449
515
|
end
|
|
450
516
|
eof
|
|
@@ -467,8 +533,8 @@ module YARD
|
|
|
467
533
|
begin; undef on_#{kw}_add; rescue NameError; end
|
|
468
534
|
def on_#{kw}_add(list, item)
|
|
469
535
|
last = @source[@ns_charno,1] == "\n" ? @ns_charno - 1 : @ns_charno
|
|
470
|
-
list.source_range = (list.source_range.
|
|
471
|
-
list.line_range = (list.line_range.
|
|
536
|
+
list.source_range = (list.source_range.begin..last)
|
|
537
|
+
list.line_range = (list.line_range.begin..lineno)
|
|
472
538
|
list.push(item)
|
|
473
539
|
list
|
|
474
540
|
end
|
|
@@ -479,9 +545,9 @@ module YARD
|
|
|
479
545
|
node = visit_event_arr(LiteralNode.new(:string_literal, args))
|
|
480
546
|
if args.size == 1
|
|
481
547
|
r = args[0].source_range
|
|
482
|
-
if node.source_range != Range.new(r.
|
|
548
|
+
if node.source_range != Range.new(r.begin - 1, r.end + 1)
|
|
483
549
|
klass = AstNode.node_class_for(node[0].type)
|
|
484
|
-
r = Range.new(node.source_range.
|
|
550
|
+
r = Range.new(node.source_range.begin + 1, node.source_range.end - 1)
|
|
485
551
|
node[0] = klass.new(node[0].type, [@source[r]], :line => node.line_range, :char => r)
|
|
486
552
|
end
|
|
487
553
|
end
|
|
@@ -567,7 +633,7 @@ module YARD
|
|
|
567
633
|
@comments_flags[lineno] = @comments_flags[lineno - 1]
|
|
568
634
|
@comments_flags.delete(lineno - 1)
|
|
569
635
|
range = @comments_range.delete(lineno - 1)
|
|
570
|
-
source_range = range.
|
|
636
|
+
source_range = range.begin..source_range.end
|
|
571
637
|
comment = append_comment + "\n" + comment
|
|
572
638
|
end
|
|
573
639
|
|
|
@@ -603,6 +669,7 @@ module YARD
|
|
|
603
669
|
alias compile_error on_parse_error
|
|
604
670
|
|
|
605
671
|
def comment_starts_line?(charno)
|
|
672
|
+
return true if @source[charno] == "\n"
|
|
606
673
|
(charno - 1).downto(0) do |i|
|
|
607
674
|
ch = @source[i]
|
|
608
675
|
break if ch == "\n"
|
|
@@ -613,7 +680,7 @@ module YARD
|
|
|
613
680
|
|
|
614
681
|
def insert_comments
|
|
615
682
|
root.traverse do |node|
|
|
616
|
-
next if
|
|
683
|
+
next if COMMENT_SKIP_NODE_TYPES.include?(node.type) || node.parent.type != :list
|
|
617
684
|
|
|
618
685
|
# never attach comments to if/unless mod nodes
|
|
619
686
|
if node.type == :if_mod || node.type == :unless_mod
|
|
@@ -621,11 +688,13 @@ module YARD
|
|
|
621
688
|
end
|
|
622
689
|
|
|
623
690
|
# check upwards from line before node; check node's line at the end
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
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
|
|
629
698
|
end
|
|
630
699
|
end
|
|
631
700
|
|
|
@@ -650,6 +719,23 @@ module YARD
|
|
|
650
719
|
end
|
|
651
720
|
end unless @comments.empty?
|
|
652
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
|
+
|
|
653
739
|
# insert all remaining comments
|
|
654
740
|
@comments.each do |line, _comment|
|
|
655
741
|
add_comment(line, nil, root, true)
|
|
@@ -661,6 +747,11 @@ module YARD
|
|
|
661
747
|
def add_comment(line, node = nil, before_node = nil, into = false)
|
|
662
748
|
comment = @comments[line]
|
|
663
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
|
|
664
755
|
line_range = ((line - comment.count("\n"))..line)
|
|
665
756
|
if node.nil?
|
|
666
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
|
|
|
@@ -476,9 +477,8 @@ module YARD
|
|
|
476
477
|
content.force_encoding('binary')
|
|
477
478
|
ENCODING_BYTE_ORDER_MARKS.each do |encoding, bom|
|
|
478
479
|
bom.force_encoding('binary')
|
|
479
|
-
if content
|
|
480
|
-
content.force_encoding(encoding)
|
|
481
|
-
return content
|
|
480
|
+
if content.start_with?(bom)
|
|
481
|
+
return content.sub(bom, '').force_encoding(encoding)
|
|
482
482
|
end
|
|
483
483
|
end
|
|
484
484
|
content.force_encoding('utf-8') # UTF-8 is default encoding
|
|
@@ -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
|
|
@@ -132,7 +139,8 @@ module YARD
|
|
|
132
139
|
|
|
133
140
|
path.scan(split_on_separators_match).each do |part, sep|
|
|
134
141
|
cur_obj = nil
|
|
135
|
-
pos +=
|
|
142
|
+
pos += part.length
|
|
143
|
+
pos += sep.length
|
|
136
144
|
parsed_end = pos == path.length
|
|
137
145
|
|
|
138
146
|
if !last_obj || (!parsed_end && !last_obj.is_a?(CodeObjects::NamespaceObject))
|
|
@@ -88,7 +88,7 @@ module YARD
|
|
|
88
88
|
# of status, headers, and body wrapped in an array.
|
|
89
89
|
def call(request)
|
|
90
90
|
self.request = request
|
|
91
|
-
self.path ||= request.path_info[1..-1]
|
|
91
|
+
self.path ||= File.cleanpath(request.path_info[1..-1])
|
|
92
92
|
self.headers = {'Content-Type' => 'text/html'}
|
|
93
93
|
self.body = ''
|
|
94
94
|
self.status = 200
|
|
@@ -119,7 +119,7 @@ module YARD
|
|
|
119
119
|
# def run
|
|
120
120
|
# self.body = 'ERROR! The System is down!'
|
|
121
121
|
# self.status = 500
|
|
122
|
-
# self.headers['
|
|
122
|
+
# self.headers['Content-Type'] = 'text/plain'
|
|
123
123
|
# end
|
|
124
124
|
# end
|
|
125
125
|
#
|
|
@@ -94,16 +94,16 @@ module YARD
|
|
|
94
94
|
end
|
|
95
95
|
|
|
96
96
|
def call_with_fork(request, &block)
|
|
97
|
-
reader, writer
|
|
97
|
+
IO.pipe(:binmode => true) do |reader, writer|
|
|
98
|
+
fork do
|
|
99
|
+
log.debug "[pid=#{Process.pid}] fork serving: #{request.path}"
|
|
100
|
+
reader.close
|
|
101
|
+
writer.print(Marshal.dump(call_without_fork(request, &block)))
|
|
102
|
+
end
|
|
98
103
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
reader.close
|
|
102
|
-
writer.print(Marshal.dump(call_without_fork(request, &block)))
|
|
104
|
+
writer.close
|
|
105
|
+
Marshal.load(reader.read)
|
|
103
106
|
end
|
|
104
|
-
|
|
105
|
-
writer.close
|
|
106
|
-
Marshal.load(reader.read)
|
|
107
107
|
end
|
|
108
108
|
|
|
109
109
|
def can_fork?
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
require 'webrick/httputils'
|
|
3
2
|
|
|
4
3
|
module YARD
|
|
5
4
|
module Server
|
|
@@ -7,7 +6,7 @@ module YARD
|
|
|
7
6
|
# Include this module to get access to {#static_template_file?}
|
|
8
7
|
# and {favicon?} helpers.
|
|
9
8
|
module StaticFileHelpers
|
|
10
|
-
include
|
|
9
|
+
include Server::HTTPUtils
|
|
11
10
|
|
|
12
11
|
# Serves an empty favicon.
|
|
13
12
|
# @raise [FinishRequest] finalizes an empty body if the path matches
|