rbs 2.0.0 → 2.2.2

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 (208) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/comments.yml +34 -0
  3. data/.github/workflows/ruby.yml +5 -0
  4. data/CHANGELOG.md +82 -0
  5. data/README.md +6 -1
  6. data/Rakefile +56 -21
  7. data/core/array.rbs +2866 -1086
  8. data/core/basic_object.rbs +150 -30
  9. data/core/binding.rbs +33 -0
  10. data/core/builtin.rbs +4 -4
  11. data/core/class.rbs +43 -5
  12. data/core/comparable.rbs +57 -0
  13. data/core/complex.rbs +170 -4
  14. data/core/constants.rbs +51 -0
  15. data/core/deprecated.rbs +7 -0
  16. data/core/dir.rbs +305 -20
  17. data/core/encoding.rbs +1214 -77
  18. data/core/enumerable.rbs +2173 -234
  19. data/core/enumerator.rbs +448 -182
  20. data/core/env.rbs +448 -1
  21. data/core/errno.rbs +1 -10
  22. data/core/errors.rbs +152 -2
  23. data/core/exception.rbs +201 -127
  24. data/core/false_class.rbs +27 -0
  25. data/core/fiber.rbs +118 -37
  26. data/core/fiber_error.rbs +8 -9
  27. data/core/file.rbs +1060 -142
  28. data/core/file_test.rbs +287 -32
  29. data/core/float.rbs +776 -300
  30. data/core/gc.rbs +185 -34
  31. data/core/global_variables.rbs +5 -1
  32. data/core/hash.rbs +1582 -649
  33. data/core/integer.rbs +974 -204
  34. data/core/io/buffer.rbs +710 -0
  35. data/core/io/wait.rbs +29 -8
  36. data/core/io.rbs +2438 -417
  37. data/core/kernel.rbs +2319 -318
  38. data/core/marshal.rbs +37 -2
  39. data/core/match_data.rbs +123 -6
  40. data/core/math.rbs +126 -6
  41. data/core/method.rbs +226 -102
  42. data/core/module.rbs +421 -45
  43. data/core/nil_class.rbs +64 -0
  44. data/core/numeric.rbs +620 -142
  45. data/core/object.rbs +453 -81
  46. data/core/object_space.rbs +92 -2
  47. data/core/proc.rbs +482 -285
  48. data/core/process.rbs +443 -34
  49. data/core/ractor.rbs +232 -9
  50. data/core/random.rbs +151 -52
  51. data/core/range.rbs +885 -160
  52. data/core/rational.rbs +122 -6
  53. data/core/rb_config.rbs +14 -4
  54. data/core/refinement.rbs +44 -0
  55. data/core/regexp.rbs +156 -14
  56. data/core/ruby_vm.rbs +42 -3
  57. data/core/signal.rbs +78 -39
  58. data/core/string.rbs +2123 -567
  59. data/core/string_io.rbs +204 -0
  60. data/core/struct.rbs +283 -28
  61. data/core/symbol.rbs +304 -30
  62. data/core/thread.rbs +1288 -688
  63. data/core/thread_group.rbs +66 -10
  64. data/core/time.rbs +643 -217
  65. data/core/trace_point.rbs +100 -12
  66. data/core/true_class.rbs +24 -0
  67. data/core/unbound_method.rbs +73 -7
  68. data/core/warning.rbs +37 -12
  69. data/docs/CONTRIBUTING.md +40 -34
  70. data/docs/stdlib.md +3 -102
  71. data/docs/syntax.md +54 -11
  72. data/ext/rbs_extension/extconf.rb +1 -0
  73. data/ext/rbs_extension/lexer.h +5 -0
  74. data/ext/rbs_extension/lexstate.c +6 -0
  75. data/ext/rbs_extension/parser.c +85 -10
  76. data/ext/rbs_extension/ruby_objs.c +4 -2
  77. data/ext/rbs_extension/ruby_objs.h +2 -2
  78. data/goodcheck.yml +0 -11
  79. data/lib/rbs/annotate/annotations.rb +197 -0
  80. data/lib/rbs/annotate/formatter.rb +80 -0
  81. data/lib/rbs/annotate/rdoc_annotator.rb +398 -0
  82. data/lib/rbs/annotate/rdoc_source.rb +120 -0
  83. data/lib/rbs/annotate.rb +6 -0
  84. data/lib/rbs/ast/members.rb +21 -13
  85. data/lib/rbs/buffer.rb +17 -11
  86. data/lib/rbs/cli.rb +48 -1
  87. data/lib/rbs/definition_builder/method_builder.rb +28 -16
  88. data/lib/rbs/definition_builder.rb +6 -2
  89. data/lib/rbs/environment.rb +8 -4
  90. data/lib/rbs/location_aux.rb +12 -0
  91. data/lib/rbs/namespace.rb +1 -1
  92. data/lib/rbs/prototype/rb.rb +12 -0
  93. data/lib/rbs/type_alias_regularity.rb +6 -4
  94. data/lib/rbs/type_name.rb +1 -1
  95. data/lib/rbs/types.rb +1 -1
  96. data/lib/rbs/validator.rb +6 -0
  97. data/lib/rbs/version.rb +1 -1
  98. data/lib/rbs/writer.rb +54 -4
  99. data/lib/rbs.rb +0 -2
  100. data/schema/typeParam.json +3 -3
  101. data/sig/annotate/annotations.rbs +102 -0
  102. data/sig/annotate/formatter.rbs +24 -0
  103. data/sig/annotate/rdoc_annotater.rbs +82 -0
  104. data/sig/annotate/rdoc_source.rbs +30 -0
  105. data/sig/buffer.rbs +6 -2
  106. data/sig/cli.rbs +2 -0
  107. data/sig/collection/{collections.rbs → sources.rbs} +0 -0
  108. data/sig/location.rbs +6 -0
  109. data/sig/members.rbs +24 -18
  110. data/sig/method_builder.rbs +5 -4
  111. data/sig/method_types.rbs +5 -1
  112. data/sig/polyfill.rbs +78 -0
  113. data/sig/validator.rbs +3 -1
  114. data/sig/writer.rbs +79 -2
  115. data/stdlib/abbrev/0/abbrev.rbs +6 -0
  116. data/stdlib/abbrev/0/array.rbs +26 -0
  117. data/stdlib/base64/0/base64.rbs +31 -0
  118. data/stdlib/benchmark/0/benchmark.rbs +74 -3
  119. data/stdlib/bigdecimal/0/big_decimal.rbs +614 -165
  120. data/stdlib/bigdecimal-math/0/big_math.rbs +41 -64
  121. data/stdlib/cgi/0/core.rbs +649 -21
  122. data/stdlib/coverage/0/coverage.rbs +164 -2
  123. data/stdlib/csv/0/csv.rbs +2862 -398
  124. data/stdlib/date/0/date.rbs +483 -25
  125. data/stdlib/date/0/date_time.rbs +187 -12
  126. data/stdlib/dbm/0/dbm.rbs +152 -17
  127. data/stdlib/digest/0/digest.rbs +146 -0
  128. data/stdlib/erb/0/erb.rbs +65 -245
  129. data/stdlib/fiber/0/fiber.rbs +73 -91
  130. data/stdlib/fileutils/0/fileutils.rbs +301 -1
  131. data/stdlib/find/0/find.rbs +9 -0
  132. data/stdlib/forwardable/0/forwardable.rbs +65 -1
  133. data/stdlib/io-console/0/io-console.rbs +227 -15
  134. data/stdlib/ipaddr/0/ipaddr.rbs +161 -0
  135. data/stdlib/json/0/json.rbs +1147 -145
  136. data/stdlib/logger/0/formatter.rbs +24 -0
  137. data/stdlib/logger/0/log_device.rbs +64 -0
  138. data/stdlib/logger/0/logger.rbs +165 -13
  139. data/stdlib/logger/0/period.rbs +10 -0
  140. data/stdlib/logger/0/severity.rbs +26 -0
  141. data/stdlib/monitor/0/monitor.rbs +163 -0
  142. data/stdlib/mutex_m/0/mutex_m.rbs +35 -6
  143. data/stdlib/net-http/0/manifest.yaml +1 -0
  144. data/stdlib/net-http/0/net-http.rbs +1513 -683
  145. data/stdlib/nkf/0/nkf.rbs +372 -0
  146. data/stdlib/objspace/0/objspace.rbs +149 -90
  147. data/stdlib/openssl/0/openssl.rbs +8108 -71
  148. data/stdlib/optparse/0/optparse.rbs +487 -19
  149. data/stdlib/pathname/0/pathname.rbs +425 -124
  150. data/stdlib/prettyprint/0/prettyprint.rbs +120 -99
  151. data/stdlib/prime/0/integer-extension.rbs +20 -2
  152. data/stdlib/prime/0/prime.rbs +88 -21
  153. data/stdlib/pstore/0/pstore.rbs +102 -0
  154. data/stdlib/pty/0/pty.rbs +64 -14
  155. data/stdlib/resolv/0/resolv.rbs +420 -31
  156. data/stdlib/rubygems/0/basic_specification.rbs +4 -1
  157. data/stdlib/rubygems/0/config_file.rbs +33 -1
  158. data/stdlib/rubygems/0/dependency_installer.rbs +4 -3
  159. data/stdlib/rubygems/0/installer.rbs +13 -1
  160. data/stdlib/rubygems/0/path_support.rbs +4 -1
  161. data/stdlib/rubygems/0/platform.rbs +5 -1
  162. data/stdlib/rubygems/0/request_set.rbs +44 -2
  163. data/stdlib/rubygems/0/requirement.rbs +65 -2
  164. data/stdlib/rubygems/0/rubygems.rbs +407 -0
  165. data/stdlib/rubygems/0/source_list.rbs +13 -0
  166. data/stdlib/rubygems/0/specification.rbs +21 -1
  167. data/stdlib/rubygems/0/stream_ui.rbs +3 -1
  168. data/stdlib/rubygems/0/uninstaller.rbs +8 -1
  169. data/stdlib/rubygems/0/version.rbs +60 -157
  170. data/stdlib/securerandom/0/securerandom.rbs +44 -0
  171. data/stdlib/set/0/set.rbs +423 -109
  172. data/stdlib/shellwords/0/shellwords.rbs +55 -77
  173. data/stdlib/singleton/0/singleton.rbs +20 -0
  174. data/stdlib/socket/0/addrinfo.rbs +210 -9
  175. data/stdlib/socket/0/basic_socket.rbs +103 -11
  176. data/stdlib/socket/0/ip_socket.rbs +31 -9
  177. data/stdlib/socket/0/socket.rbs +586 -38
  178. data/stdlib/socket/0/tcp_server.rbs +22 -2
  179. data/stdlib/socket/0/tcp_socket.rbs +12 -1
  180. data/stdlib/socket/0/udp_socket.rbs +25 -2
  181. data/stdlib/socket/0/unix_server.rbs +22 -2
  182. data/stdlib/socket/0/unix_socket.rbs +45 -5
  183. data/stdlib/strscan/0/string_scanner.rbs +210 -9
  184. data/stdlib/tempfile/0/tempfile.rbs +58 -10
  185. data/stdlib/time/0/time.rbs +208 -116
  186. data/stdlib/timeout/0/timeout.rbs +10 -0
  187. data/stdlib/tmpdir/0/tmpdir.rbs +13 -4
  188. data/stdlib/tsort/0/cyclic.rbs +1 -0
  189. data/stdlib/tsort/0/interfaces.rbs +1 -0
  190. data/stdlib/tsort/0/tsort.rbs +42 -0
  191. data/stdlib/uri/0/common.rbs +57 -8
  192. data/stdlib/uri/0/file.rbs +55 -109
  193. data/stdlib/uri/0/ftp.rbs +6 -3
  194. data/stdlib/uri/0/generic.rbs +558 -329
  195. data/stdlib/uri/0/http.rbs +60 -114
  196. data/stdlib/uri/0/https.rbs +8 -102
  197. data/stdlib/uri/0/ldap.rbs +143 -137
  198. data/stdlib/uri/0/ldaps.rbs +8 -102
  199. data/stdlib/uri/0/mailto.rbs +3 -0
  200. data/stdlib/uri/0/rfc2396_parser.rbs +66 -26
  201. data/stdlib/uri/0/ws.rbs +6 -3
  202. data/stdlib/uri/0/wss.rbs +5 -3
  203. data/stdlib/yaml/0/dbm.rbs +151 -87
  204. data/stdlib/yaml/0/store.rbs +6 -0
  205. data/stdlib/zlib/0/zlib.rbs +90 -31
  206. metadata +18 -6
  207. data/lib/rbs/location.rb +0 -221
  208. data/sig/char_scanner.rbs +0 -9
@@ -0,0 +1,197 @@
1
+ module RBS
2
+ module Annotate
3
+ class Annotations
4
+ class Skip
5
+ attr_reader :annotation, :skip_children
6
+
7
+ def initialize(annotation:, skip_children:)
8
+ @annotation = annotation
9
+ @skip_children = skip_children
10
+ end
11
+
12
+ def hash
13
+ self.class.hash ^ annotation.hash ^ skip_children.hash
14
+ end
15
+
16
+ def ==(other)
17
+ other.is_a?(Skip) &&
18
+ other.skip_children == skip_children &&
19
+ other.annotation == annotation
20
+ end
21
+
22
+ alias eql? ==
23
+ end
24
+
25
+ class Source
26
+ attr_reader :annotation
27
+ attr_reader :include_source, :skip_source
28
+
29
+ def initialize(annotation:, include: nil, skip: nil)
30
+ @annotation = annotation
31
+ @include_source = include
32
+ @skip_source = skip
33
+ end
34
+
35
+ def hash
36
+ self.class.hash ^ annotation.hash ^ include_source.hash ^ skip_source.hash
37
+ end
38
+
39
+ def ==(other)
40
+ other.is_a?(Source) &&
41
+ other.annotation == annotation &&
42
+ other.include_source == include_source &&
43
+ other.skip_source == skip_source
44
+ end
45
+
46
+ alias eql? ==
47
+ end
48
+
49
+ class Copy
50
+ attr_reader :annotation, :source
51
+
52
+ def initialize(annotation:, source:)
53
+ @annotation = annotation
54
+ @source = source
55
+ end
56
+
57
+ def type_name
58
+ name, _ = partition
59
+ name
60
+ end
61
+
62
+ def method_name
63
+ _, m = partition
64
+ if m
65
+ m[1]
66
+ end
67
+ end
68
+
69
+ def singleton?
70
+ _, m = partition
71
+ if m
72
+ m[0]
73
+ else
74
+ false
75
+ end
76
+ end
77
+
78
+ def hash
79
+ self.class.hash ^ annotation.hash ^ source.hash
80
+ end
81
+
82
+ def ==(other)
83
+ other.is_a?(Copy) &&
84
+ other.annotation == annotation &&
85
+ other.source == source
86
+ end
87
+
88
+ alias eql? ==
89
+
90
+ def partition
91
+ case
92
+ when match = source.match(/(?<constant_name>[^#]+)#(?<method_name>.+)/)
93
+ [
94
+ TypeName(match[:constant_name] || raise),
95
+ [
96
+ false,
97
+ (match[:method_name] or raise).to_sym
98
+ ]
99
+ ]
100
+ when match = source.match(/(?<constant_name>[^#]+)\.(?<method_name>.+)/)
101
+ [
102
+ TypeName(match[:constant_name] || raise),
103
+ [
104
+ true,
105
+ (match[:method_name] or raise).to_sym
106
+ ]
107
+ ]
108
+ else
109
+ [
110
+ TypeName(source),
111
+ nil
112
+ ]
113
+ end
114
+ end
115
+ end
116
+
117
+ def self.parse(annotation)
118
+ string = annotation.string
119
+
120
+ case
121
+ when match = string.match(/\Aannotate:rdoc:skip(:all)?\Z/)
122
+ Skip.new(
123
+ annotation: annotation,
124
+ skip_children: string.end_with?(":all")
125
+ )
126
+ when match = string.match(/\Aannotate:rdoc:source:from=(?<path>.+)\Z/)
127
+ Source.new(
128
+ annotation: annotation,
129
+ include: (match[:path] or raise).strip
130
+ )
131
+ when match = string.match(/\Aannotate:rdoc:source:skip=(?<path>.+)\Z/)
132
+ Source.new(
133
+ annotation: annotation,
134
+ skip: (match[:path] or raise).strip
135
+ )
136
+ when match = string.match(/\Aannotate:rdoc:copy:(?<name>.+)\Z/)
137
+ Copy.new(
138
+ annotation: annotation,
139
+ source: (match[:name] or raise).strip
140
+ )
141
+ end
142
+ end
143
+
144
+ attr_reader :items
145
+
146
+ def initialize(items)
147
+ @items = items
148
+ end
149
+
150
+ def skip?
151
+ items.any? {|a| a.is_a?(Skip) }
152
+ end
153
+
154
+ def skip_all?
155
+ items.any? {|a| a.is_a?(Skip) && a.skip_children }
156
+ end
157
+
158
+ def copy_annotation
159
+ _ = items.find {|a| a.is_a?(Copy) }
160
+ end
161
+
162
+ def test_path(path)
163
+ # @type var source_items: Array[Source]
164
+ source_items = _ = items.select {|item| item.is_a?(Source) }
165
+
166
+ return true if source_items.empty?
167
+
168
+ result = source_items[0].include_source == nil
169
+
170
+ items.each do |a|
171
+ if a.is_a?(Source)
172
+ if pat = a.include_source
173
+ if test_path_string(pat, path)
174
+ result = true
175
+ end
176
+ end
177
+
178
+ if pat = a.skip_source
179
+ if test_path_string(pat, path)
180
+ result = false
181
+ end
182
+ end
183
+ end
184
+ end
185
+
186
+ result
187
+ end
188
+
189
+ def test_path_string(pattern, string)
190
+ return true if pattern == string
191
+ return true if string.start_with?(pattern + File::SEPARATOR)
192
+
193
+ false
194
+ end
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,80 @@
1
+ module RBS
2
+ module Annotate
3
+ class Formatter
4
+ attr_reader :buffer
5
+
6
+ def initialize()
7
+ @buffer = ""
8
+ @pending_separator = nil
9
+ end
10
+
11
+ def <<(s)
12
+ if s
13
+ if s.is_a?(RDoc::Markup::Document)
14
+ s = self.class.translate(s) or raise
15
+ end
16
+
17
+ s.rstrip!
18
+
19
+ unless s.empty?
20
+ if ss = @pending_separator
21
+ buffer << ss
22
+ buffer << "\n"
23
+ @pending_separator = nil
24
+ end
25
+
26
+ buffer << s
27
+ buffer << "\n"
28
+ end
29
+ end
30
+
31
+ self
32
+ end
33
+
34
+ def margin(separator: "")
35
+ unless buffer.empty?
36
+ @pending_separator = separator
37
+ end
38
+
39
+ self
40
+ end
41
+
42
+ def empty?
43
+ buffer.empty?
44
+ end
45
+
46
+ def format(newline_at_end:)
47
+ unless buffer.empty?
48
+ if newline_at_end
49
+ buffer.strip + "\n\n"
50
+ else
51
+ buffer.strip + "\n"
52
+ end
53
+ else
54
+ buffer
55
+ end
56
+ end
57
+
58
+ def self.each_part(doc, &block)
59
+ if block
60
+ if doc.file
61
+ yield doc
62
+ else
63
+ doc.each do |d|
64
+ each_part(d, &block)
65
+ end
66
+ end
67
+ else
68
+ enum_for :each_part, doc
69
+ end
70
+ end
71
+
72
+ def self.translate(doc)
73
+ if doc.file
74
+ formatter = RDoc::Markup::ToMarkdown.new
75
+ doc.accept(formatter).strip.lines.map(&:rstrip).join("\n")
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,398 @@
1
+ module RBS
2
+ module Annotate
3
+ class RDocAnnotator
4
+ attr_reader :source
5
+ attr_accessor :include_arg_lists, :include_filename
6
+
7
+ def initialize(source:)
8
+ @source = source
9
+
10
+ @include_arg_lists = true
11
+ @include_filename = true
12
+ end
13
+
14
+ def annotate_file(path, preserve:)
15
+ content = path.read()
16
+
17
+ decls = Parser.parse_signature(content)
18
+
19
+ annotate_decls(decls)
20
+
21
+ path.open("w") do |io|
22
+ Writer.new(out: io).preserve!(preserve: preserve).write(decls)
23
+ end
24
+ end
25
+
26
+ def annotate_decls(decls, outer: [])
27
+ decls.each do |decl|
28
+ case decl
29
+ when AST::Declarations::Class, AST::Declarations::Module
30
+ annotate_class(decl, outer: outer)
31
+ when AST::Declarations::Constant
32
+ annotate_constant(decl, outer: outer)
33
+ end
34
+ end
35
+ end
36
+
37
+ def each_part(subjects, tester:)
38
+ if block_given?
39
+ subjects.each do |subject, docs|
40
+ Formatter.each_part(subject.comment) do |doc|
41
+ if tester.test_path(doc.file || raise)
42
+ yield [doc, subject]
43
+ end
44
+ end
45
+ end
46
+ else
47
+ enum_for :each_part, tester: tester
48
+ end
49
+ end
50
+
51
+ def resolve_doc_source(copy, tester:)
52
+ case
53
+ when copy && (mn = copy.method_name) && copy.singleton?
54
+ doc_for_method(copy.type_name, singleton_method: mn, tester: tester)
55
+ when copy && (mn = copy.method_name) && !copy.singleton?
56
+ doc_for_method(copy.type_name, instance_method: mn, tester: tester)
57
+ when copy
58
+ doc_for_class(copy.type_name, tester: tester) || doc_for_constant(copy.type_name, tester: tester)
59
+ else
60
+ yield
61
+ end
62
+ end
63
+
64
+ def doc_for_class(name, tester:)
65
+ if clss = source.find_class(name)
66
+ formatter = Formatter.new()
67
+
68
+ each_part(clss, tester: tester) do |doc, _|
69
+ text = Formatter.translate(doc) or next
70
+
71
+ unless text.empty?
72
+ if include_filename
73
+ formatter << "<!-- rdoc-file=#{doc.file} -->"
74
+ end
75
+ formatter << text
76
+
77
+ formatter.margin
78
+ end
79
+ end
80
+
81
+ formatter.format(newline_at_end: true)
82
+ end
83
+ end
84
+
85
+ def doc_for_constant(name, tester:)
86
+ if constants = source.find_const(name)
87
+ formatter = Formatter.new
88
+
89
+ each_part(constants, tester: tester) do |doc, _|
90
+ text = Formatter.translate(doc) or next
91
+
92
+ unless text.empty?
93
+ if include_filename
94
+ formatter << "<!-- rdoc-file=#{doc.file} -->"
95
+ end
96
+
97
+ formatter << text
98
+
99
+ formatter.margin
100
+ end
101
+ end
102
+
103
+ formatter.format(newline_at_end: true)
104
+ end
105
+ end
106
+
107
+ def doc_for_method0(typename, instance_method: nil, singleton_method: nil, tester:)
108
+ ms = source.find_method(typename, instance_method: instance_method) if instance_method
109
+ ms = source.find_method(typename, singleton_method: singleton_method) if singleton_method
110
+
111
+ if ms
112
+ formatter = Formatter.new
113
+
114
+ each_part(ms, tester: tester) do |doc, method|
115
+ text = Formatter.translate(doc) or next
116
+ # @type var as: String?
117
+ as = (_ = method).arglists
118
+
119
+ if include_arg_lists && as
120
+ formatter << "<!--"
121
+ formatter << " rdoc-file=#{doc.file}" if include_filename
122
+ as.chomp.split("\n").each do |line|
123
+ formatter << " - #{line.strip}"
124
+ end
125
+ formatter << "-->"
126
+ else
127
+ if include_filename
128
+ formatter << "<!-- rdoc-file=#{doc.file} -->"
129
+ end
130
+ end
131
+
132
+ unless text.empty?
133
+ formatter << text
134
+ end
135
+
136
+ formatter.margin(separator: "----")
137
+ end
138
+
139
+ formatter.format(newline_at_end: false)
140
+ end
141
+ end
142
+
143
+ def doc_for_method(typename, instance_method: nil, singleton_method: nil, tester:)
144
+ formatter = Formatter.new()
145
+
146
+ case
147
+ when method = instance_method
148
+ doc = doc_for_alias(typename, name: method, singleton: false, tester: tester)
149
+ doc = doc_for_method0(typename, instance_method: method, tester: tester) if !doc || doc.empty?
150
+ if !doc || doc.empty?
151
+ if (s = method.to_s) =~ /\A[a-zA-Z_]/
152
+ # may be attribute
153
+ doc =
154
+ if s.end_with?("=")
155
+ doc_for_attribute(typename, s.delete_suffix("=").to_sym, require: "W", singleton: false, tester: tester)
156
+ else
157
+ doc_for_attribute(typename, s.to_sym, require: "R", singleton: false, tester: tester)
158
+ end
159
+ end
160
+ end
161
+ when method = singleton_method
162
+ doc = doc_for_alias(typename, name: method, singleton: true, tester: tester)
163
+ doc = doc_for_method0(typename, singleton_method: method, tester: tester) if !doc || doc.empty?
164
+ if !doc || doc.empty?
165
+ if (s = method.to_s) =~ /\A[a-zA-Z_]/
166
+ # may be attribute
167
+ doc =
168
+ if s.end_with?("=")
169
+ doc_for_attribute(typename, s.delete_suffix("=").to_sym, require: "W", singleton: true, tester: tester)
170
+ else
171
+ doc_for_attribute(typename, s.to_sym, require: "R", singleton: true, tester: tester)
172
+ end
173
+ end
174
+ end
175
+ else
176
+ raise
177
+ end
178
+
179
+ if doc
180
+ formatter << doc
181
+ formatter.format(newline_at_end: true)
182
+ end
183
+ end
184
+
185
+ def doc_for_alias(typename, name:, singleton:, tester:)
186
+ if as =
187
+ if singleton
188
+ source.find_method(typename, singleton_method: name)
189
+ else
190
+ source.find_method(typename, instance_method: name)
191
+ end
192
+
193
+ formatter = Formatter.new
194
+
195
+ each_part(as, tester: tester) do |doc, obj|
196
+ # @type var method: RDoc::AnyMethod
197
+ method = _ = obj
198
+
199
+ if method.is_alias_for
200
+ text = Formatter.translate(doc) or next
201
+
202
+ unless text.empty?
203
+ formatter << "<!-- rdoc-file=#{doc.file} -->" if include_filename
204
+ formatter << text
205
+ end
206
+ end
207
+ end
208
+
209
+ formatter.format(newline_at_end: true)
210
+ end
211
+ end
212
+
213
+ def doc_for_attribute(typename, attr_name, require: nil, singleton:, tester:)
214
+ if as = source.find_attribute(typename, attr_name, singleton: singleton)
215
+ as = as.select do |attr|
216
+ case require
217
+ when "R"
218
+ attr.rw == "R" || attr.rw == "RW"
219
+ when "W"
220
+ attr.rw == "W" || attr.rw == "RW"
221
+ else
222
+ true
223
+ end
224
+ end
225
+
226
+ return if as.empty?
227
+
228
+ formatter = Formatter.new()
229
+
230
+ each_part(as, tester: tester) do |doc, obj|
231
+ if text = Formatter.translate(doc)
232
+ unless text.empty?
233
+ formatter << "<!-- rdoc-file=#{doc.file} -->" if include_filename
234
+ formatter << text
235
+ end
236
+ end
237
+ end
238
+
239
+ formatter.format(newline_at_end: true)
240
+ end
241
+ end
242
+
243
+ def annotate_class(decl, outer:)
244
+ annots = annotations(decl)
245
+
246
+ full_name = resolve_name(decl.name, outer: outer)
247
+ unless annots.skip?
248
+ text = resolve_doc_source(annots.copy_annotation, tester: annots) { doc_for_class(full_name, tester: annots) }
249
+ end
250
+
251
+ replace_comment(decl, text)
252
+
253
+ unless annots.skip_all?
254
+ outer_ = outer + [decl.name.to_namespace]
255
+
256
+ decl.each_member do |member|
257
+ case member
258
+ when AST::Members::MethodDefinition
259
+ annotate_method(full_name, member)
260
+ when AST::Members::Alias
261
+ annotate_alias(full_name, member)
262
+ when AST::Members::AttrReader, AST::Members::AttrAccessor, AST::Members::AttrWriter
263
+ annotate_attribute(full_name, member)
264
+ end
265
+ end
266
+
267
+ annotate_decls(decl.each_decl.to_a, outer: outer_)
268
+ end
269
+ end
270
+
271
+ def annotate_constant(const, outer:)
272
+ annots = Annotations.new([])
273
+
274
+ full_name = resolve_name(const.name, outer: outer)
275
+ text = doc_for_constant(full_name, tester: annots)
276
+
277
+ replace_comment(const, text)
278
+ end
279
+
280
+ def annotate_alias(typename, als)
281
+ annots = annotations(als)
282
+
283
+ unless annots.skip?
284
+ text = resolve_doc_source(annots.copy_annotation, tester: annots) do
285
+ case als.kind
286
+ when :instance
287
+ doc_for_method(typename, instance_method: als.new_name, tester: annots)
288
+ when :singleton
289
+ doc_for_method(typename, singleton_method: als.new_name, tester: annots)
290
+ end
291
+ end
292
+ end
293
+
294
+ replace_comment(als, text)
295
+ end
296
+
297
+ def join_docs(docs, separator: "----")
298
+ formatter = Formatter.new()
299
+
300
+ docs.each do |doc|
301
+ formatter << doc
302
+ formatter.margin(separator: separator)
303
+ end
304
+
305
+ unless formatter.empty?
306
+ formatter.format(newline_at_end: true)
307
+ end
308
+ end
309
+
310
+ def annotate_method(typename, method)
311
+ annots = annotations(method)
312
+
313
+ unless annots.skip?
314
+ text = resolve_doc_source(annots.copy_annotation, tester: annots) {
315
+ case method.kind
316
+ when :singleton
317
+ doc_for_method(typename, singleton_method: method.name, tester: annots)
318
+ when :instance
319
+ if method.name == :initialize
320
+ doc_for_method(typename, instance_method: :initialize, tester: annots) ||
321
+ doc_for_method(typename, singleton_method: :new, tester: annots)
322
+ else
323
+ doc_for_method(typename, instance_method: method.name, tester: annots)
324
+ end
325
+ when :singleton_instance
326
+ join_docs(
327
+ [
328
+ doc_for_method(typename, singleton_method: method.name, tester: annots),
329
+ doc_for_method(typename, instance_method: method.name, tester: annots)
330
+ ].uniq
331
+ )
332
+ end
333
+ }
334
+ end
335
+
336
+ replace_comment(method, text)
337
+ end
338
+
339
+ def annotate_attribute(typename, attr)
340
+ annots = annotations(attr)
341
+
342
+ unless annots.skip?
343
+ text = resolve_doc_source(annots.copy_annotation, tester: annots) do
344
+ # @type var docs: Array[String?]
345
+ docs = []
346
+
347
+ case attr.kind
348
+ when :instance
349
+ if attr.is_a?(AST::Members::AttrReader) || attr.is_a?(AST::Members::AttrAccessor)
350
+ docs << doc_for_method(typename, instance_method: attr.name, tester: annots)
351
+ end
352
+ if attr.is_a?(AST::Members::AttrWriter) || attr.is_a?(AST::Members::AttrAccessor)
353
+ docs << doc_for_method(typename, instance_method: :"#{attr.name}=", tester: annots)
354
+ end
355
+ when :singleton
356
+ if attr.is_a?(AST::Members::AttrReader) || attr.is_a?(AST::Members::AttrAccessor)
357
+ docs << doc_for_method(typename, singleton_method: attr.name, tester: annots)
358
+ end
359
+ if attr.is_a?(AST::Members::AttrWriter) || attr.is_a?(AST::Members::AttrAccessor)
360
+ docs << doc_for_method(typename, singleton_method: :"#{attr.name}=", tester: annots)
361
+ end
362
+ end
363
+ join_docs(docs.uniq)
364
+ end
365
+ end
366
+
367
+ replace_comment(attr, text)
368
+ end
369
+
370
+ def replace_comment(commented, string)
371
+ if string
372
+ if string.empty?
373
+ commented.instance_variable_set(:@comment, nil)
374
+ else
375
+ commented.instance_variable_set(
376
+ :@comment,
377
+ AST::Comment.new(location: nil, string: string)
378
+ )
379
+ end
380
+ end
381
+ end
382
+
383
+ def resolve_name(name, outer:)
384
+ namespace = outer.inject(RBS::Namespace.root) do |ns1, ns2|
385
+ ns1 + ns2
386
+ end
387
+
388
+ name.with_prefix(namespace).relative!
389
+ end
390
+
391
+ def annotations(annots)
392
+ # @type var as: Array[Annotations::t]
393
+ as = _ = annots.annotations.map {|annot| Annotations.parse(annot) }.compact
394
+ Annotations.new(as)
395
+ end
396
+ end
397
+ end
398
+ end