rbs 4.0.3 → 4.1.3

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 (155) hide show
  1. checksums.yaml +4 -4
  2. data/.dockerignore +37 -0
  3. data/.github/dependabot.yml +1 -1
  4. data/.github/workflows/bundle-update.yml +2 -2
  5. data/.github/workflows/c-check.yml +14 -6
  6. data/.github/workflows/comments.yml +2 -2
  7. data/.github/workflows/dependabot.yml +2 -2
  8. data/.github/workflows/jruby.yml +74 -0
  9. data/.github/workflows/release-gems.yml +235 -0
  10. data/.github/workflows/ruby.yml +43 -3
  11. data/.github/workflows/rust.yml +13 -10
  12. data/.github/workflows/truffleruby.yml +54 -0
  13. data/.github/workflows/typecheck.yml +5 -2
  14. data/.github/workflows/wasm.yml +55 -0
  15. data/.github/workflows/windows.yml +5 -2
  16. data/.gitignore +8 -0
  17. data/CHANGELOG.md +113 -0
  18. data/Dockerfile.jruby +53 -0
  19. data/README.md +4 -4
  20. data/Rakefile +512 -82
  21. data/Steepfile +9 -0
  22. data/config.yml +26 -0
  23. data/core/array.rbs +243 -180
  24. data/core/builtin.rbs +7 -6
  25. data/core/class.rbs +5 -3
  26. data/core/enumerable.rbs +109 -109
  27. data/core/enumerator/product.rbs +5 -5
  28. data/core/enumerator.rbs +28 -28
  29. data/core/file.rbs +24 -1018
  30. data/core/file_constants.rbs +463 -0
  31. data/core/file_stat.rbs +534 -0
  32. data/core/float.rbs +0 -24
  33. data/core/hash.rbs +117 -101
  34. data/core/integer.rbs +21 -58
  35. data/core/io.rbs +25 -7
  36. data/core/kernel.rbs +26 -11
  37. data/core/match_data.rbs +1 -1
  38. data/core/module.rbs +88 -74
  39. data/core/numeric.rbs +3 -0
  40. data/core/object_space/weak_key_map.rbs +7 -7
  41. data/core/pathname.rbs +0 -10
  42. data/core/ractor.rbs +0 -10
  43. data/core/range.rbs +23 -23
  44. data/core/rbs/ops.rbs +154 -0
  45. data/core/rbs/unnamed/argf.rbs +3 -3
  46. data/core/ruby_vm.rbs +40 -0
  47. data/core/rubygems/errors.rbs +4 -1
  48. data/core/rubygems/requirement.rbs +0 -10
  49. data/core/rubygems/rubygems.rbs +4 -1
  50. data/core/rubygems/specification.rbs +8 -0
  51. data/core/rubygems/version.rbs +0 -160
  52. data/core/set.rbs +3 -3
  53. data/core/struct.rbs +16 -16
  54. data/core/thread.rbs +9 -14
  55. data/docs/CONTRIBUTING.md +2 -1
  56. data/docs/inline.md +65 -7
  57. data/docs/rbs_by_example.md +20 -20
  58. data/docs/release.md +247 -0
  59. data/docs/syntax.md +2 -2
  60. data/docs/wasm_serialization.md +80 -0
  61. data/ext/rbs_extension/ast_translation.c +1298 -956
  62. data/ext/rbs_extension/ast_translation.h +4 -0
  63. data/ext/rbs_extension/class_constants.c +2 -0
  64. data/ext/rbs_extension/class_constants.h +1 -0
  65. data/ext/rbs_extension/extconf.rb +1 -0
  66. data/ext/rbs_extension/legacy_location.c +11 -6
  67. data/ext/rbs_extension/main.c +139 -4
  68. data/include/rbs/ast.h +323 -298
  69. data/include/rbs/defines.h +18 -0
  70. data/include/rbs/lexer.h +1 -0
  71. data/include/rbs/serialize.h +39 -0
  72. data/lib/rbs/annotate/rdoc_annotator.rb +27 -31
  73. data/lib/rbs/ast/ruby/annotations.rb +42 -0
  74. data/lib/rbs/ast/ruby/comment_block.rb +6 -4
  75. data/lib/rbs/ast/ruby/declarations.rb +11 -1
  76. data/lib/rbs/ast/ruby/helpers/location_helper.rb +1 -1
  77. data/lib/rbs/ast/ruby/members.rb +40 -1
  78. data/lib/rbs/buffer.rb +48 -11
  79. data/lib/rbs/cli.rb +3 -5
  80. data/lib/rbs/collection/config/lockfile_generator.rb +14 -1
  81. data/lib/rbs/collection/sources/git.rb +6 -0
  82. data/lib/rbs/definition_builder/method_builder.rb +12 -6
  83. data/lib/rbs/environment.rb +10 -3
  84. data/lib/rbs/inline_parser.rb +54 -28
  85. data/lib/rbs/namespace.rb +47 -11
  86. data/lib/rbs/parser_aux.rb +4 -2
  87. data/lib/rbs/prototype/rbi.rb +193 -25
  88. data/lib/rbs/prototype/runtime.rb +2 -0
  89. data/lib/rbs/resolver/type_name_resolver.rb +12 -14
  90. data/lib/rbs/rewriter.rb +70 -0
  91. data/lib/rbs/test/type_check.rb +6 -1
  92. data/lib/rbs/type_name.rb +33 -13
  93. data/lib/rbs/unit_test/type_assertions.rb +14 -5
  94. data/lib/rbs/version.rb +1 -1
  95. data/lib/rbs/wasm/deserializer.rb +213 -0
  96. data/lib/rbs/wasm/location.rb +61 -0
  97. data/lib/rbs/wasm/parser.rb +137 -0
  98. data/lib/rbs/wasm/runtime.rb +196 -0
  99. data/lib/rbs/wasm/serialization_schema.rb +110 -0
  100. data/lib/rbs.rb +14 -2
  101. data/lib/rbs_jars.rb +39 -0
  102. data/lib/rdoc_plugin/parser.rb +5 -0
  103. data/rbs.gemspec +32 -2
  104. data/sig/annotate/rdoc_annotater.rbs +12 -9
  105. data/sig/ast/ruby/annotations.rbs +49 -0
  106. data/sig/ast/ruby/members.rbs +21 -1
  107. data/sig/buffer.rbs +19 -1
  108. data/sig/collection/config/lockfile_generator.rbs +2 -0
  109. data/sig/inline_parser.rbs +2 -0
  110. data/sig/manifest.yaml +0 -1
  111. data/sig/namespace.rbs +20 -0
  112. data/sig/parser.rbs +10 -0
  113. data/sig/prototype/rbi.rbs +33 -4
  114. data/sig/resolver/type_name_resolver.rbs +2 -4
  115. data/sig/rewriter.rbs +45 -0
  116. data/sig/typename.rbs +15 -0
  117. data/sig/unit_test/type_assertions.rbs +6 -2
  118. data/sig/wasm/deserializer.rbs +66 -0
  119. data/sig/wasm/serialization_schema.rbs +13 -0
  120. data/src/ast.c +186 -162
  121. data/src/lexer.c +220 -193
  122. data/src/lexer.re +2 -1
  123. data/src/lexstate.c +10 -1
  124. data/src/parser.c +61 -8
  125. data/src/serialize.c +958 -0
  126. data/src/util/rbs_allocator.c +14 -8
  127. data/stdlib/abbrev/0/array.rbs +1 -1
  128. data/stdlib/csv/0/csv.rbs +5 -5
  129. data/stdlib/delegate/0/delegator.rbs +2 -1
  130. data/stdlib/digest/0/digest.rbs +11 -5
  131. data/stdlib/erb/0/erb.rbs +1 -1
  132. data/stdlib/etc/0/etc.rbs +18 -4
  133. data/stdlib/fileutils/0/fileutils.rbs +21 -21
  134. data/stdlib/ipaddr/0/ipaddr.rbs +0 -5
  135. data/stdlib/json/0/json.rbs +6 -6
  136. data/stdlib/monitor/0/monitor.rbs +2 -2
  137. data/stdlib/openssl/0/openssl.rbs +46 -40
  138. data/stdlib/resolv/0/resolv.rbs +1 -1
  139. data/stdlib/shellwords/0/shellwords.rbs +1 -1
  140. data/stdlib/stringio/0/stringio.rbs +32 -10
  141. data/stdlib/strscan/0/string_scanner.rbs +74 -55
  142. data/stdlib/tempfile/0/manifest.yaml +3 -0
  143. data/stdlib/timeout/0/timeout.rbs +0 -5
  144. data/stdlib/tsort/0/cyclic.rbs +1 -1
  145. data/stdlib/tsort/0/interfaces.rbs +8 -8
  146. data/stdlib/tsort/0/tsort.rbs +9 -9
  147. data/stdlib/uri/0/generic.rbs +0 -5
  148. data/stdlib/zlib/0/gzip_reader.rbs +2 -2
  149. data/stdlib/zlib/0/zstream.rbs +0 -1
  150. data/wasm/README.md +93 -0
  151. data/wasm/rbs_wasm.c +423 -0
  152. metadata +29 -6
  153. data/.github/workflows/milestone.yml +0 -80
  154. data/.vscode/extensions.json +0 -5
  155. data/.vscode/settings.json +0 -19
@@ -119,7 +119,53 @@ module RBS
119
119
 
120
120
  class_decl = AST::Ruby::Declarations::ClassDecl.new(buffer, class_name, node, super_class)
121
121
  insert_declaration(class_decl)
122
- push_module_nesting(class_decl) do
122
+ visit_class_or_module_body(class_decl, node)
123
+ end
124
+
125
+ def visit_module_node(node)
126
+ return if skip_node?(node)
127
+
128
+ unless module_name = constant_as_type_name(node.constant_path)
129
+ diagnostics << Diagnostic::NonConstantModuleName.new(
130
+ rbs_location(node.constant_path.location),
131
+ "Module name must be a constant"
132
+ )
133
+ return
134
+ end
135
+
136
+ module_decl = AST::Ruby::Declarations::ModuleDecl.new(buffer, module_name, node)
137
+
138
+ if leading_ref = comments.leading_block(node)
139
+ unused_annotations = [] #: Array[AST::Ruby::CommentBlock::AnnotationSyntaxError | AST::Ruby::Annotations::leading_annotation]
140
+
141
+ leading_ref.block.each_paragraph([]) do |paragraph|
142
+ case paragraph
143
+ when AST::Ruby::Annotations::ModuleSelfAnnotation
144
+ module_decl.members << AST::Ruby::Members::ModuleSelfMember.new(buffer, paragraph)
145
+ when Location
146
+ # Skip
147
+ when AST::Ruby::CommentBlock::AnnotationSyntaxError
148
+ unused_annotations << paragraph
149
+ when AST::Ruby::Annotations::SkipAnnotation
150
+ # Already handled by skip_node?
151
+ else
152
+ unused_annotations << paragraph
153
+ end
154
+ end
155
+
156
+ unless unused_annotations.empty?
157
+ report_unused_annotation(*unused_annotations)
158
+ end
159
+
160
+ leading_ref.associate!
161
+ end
162
+
163
+ insert_declaration(module_decl)
164
+ visit_class_or_module_body(module_decl, node)
165
+ end
166
+
167
+ def visit_class_or_module_body(decl, node)
168
+ push_module_nesting(decl) do
123
169
  visit_child_nodes(node)
124
170
 
125
171
  node.child_nodes.each do |child_node|
@@ -137,7 +183,7 @@ module RBS
137
183
  block.each_paragraph([]) do |paragraph|
138
184
  case paragraph
139
185
  when AST::Ruby::Annotations::InstanceVariableAnnotation
140
- class_decl.members << AST::Ruby::Members::InstanceVariableMember.new(buffer, paragraph)
186
+ decl.members << AST::Ruby::Members::InstanceVariableMember.new(buffer, paragraph)
141
187
  when Location
142
188
  # Skip
143
189
  when AST::Ruby::CommentBlock::AnnotationSyntaxError
@@ -150,42 +196,22 @@ module RBS
150
196
  report_unused_annotation(*unused_annotations)
151
197
  end
152
198
 
153
- class_decl.members.sort_by! { _1.location.start_line }
154
- end
155
-
156
- def visit_module_node(node)
157
- return if skip_node?(node)
158
-
159
- unless module_name = constant_as_type_name(node.constant_path)
160
- diagnostics << Diagnostic::NonConstantModuleName.new(
161
- rbs_location(node.constant_path.location),
162
- "Module name must be a constant"
163
- )
164
- return
165
- end
166
-
167
- module_decl = AST::Ruby::Declarations::ModuleDecl.new(buffer, module_name, node)
168
- insert_declaration(module_decl)
169
- push_module_nesting(module_decl) do
170
- visit_child_nodes(node)
171
- end
172
-
173
- comments.each_enclosed_block(node) do |block|
174
- report_unused_block(block)
175
- end
199
+ decl.members.sort_by! { _1.location.start_line }
176
200
  end
177
201
 
178
202
  def visit_def_node(node)
179
203
  return if skip_node?(node)
180
204
 
181
- if node.receiver
205
+ if node.receiver && !node.receiver.is_a?(Prism::SelfNode)
182
206
  diagnostics << Diagnostic::NotImplementedYet.new(
183
207
  rbs_location(node.receiver.location),
184
- "Singleton method definition is not supported yet"
208
+ "Method definition with non-self receiver is not supported"
185
209
  )
186
210
  return
187
211
  end
188
212
 
213
+ kind = node.receiver ? :singleton : :instance #: :singleton | :instance
214
+
189
215
  case current = current_module
190
216
  when AST::Ruby::Declarations::ClassDecl, AST::Ruby::Declarations::ModuleDecl
191
217
  leading_block = comments.leading_block!(node)
@@ -199,7 +225,7 @@ module RBS
199
225
  method_type, leading_unuseds, trailing_unused = AST::Ruby::Members::MethodTypeAnnotation.build(leading_block, trailing_block, [], node)
200
226
  report_unused_annotation(trailing_unused, *leading_unuseds)
201
227
 
202
- defn = AST::Ruby::Members::DefMember.new(buffer, node.name, node, method_type, leading_block)
228
+ defn = AST::Ruby::Members::DefMember.new(buffer, node.name, node, method_type, leading_block, kind: kind)
203
229
  current.members << defn
204
230
 
205
231
  # Skip other comments in `def` node
data/lib/rbs/namespace.rb CHANGED
@@ -9,30 +9,65 @@ module RBS
9
9
  @absolute = absolute ? true : false
10
10
  end
11
11
 
12
+ # Process-wide flyweight cache. Two tries (one per `absolute` flag)
13
+ # keyed on path Symbols, with the cached Namespace stored under the
14
+ # `INTERN_LEAF` sentinel at each path's terminal node.
15
+ @intern_mutex = Mutex.new
16
+ @intern_trie_absolute = {}
17
+ @intern_trie_relative = {}
18
+ INTERN_LEAF = Module.new
19
+
20
+ # Returns a canonical `Namespace` instance for the given `path` /
21
+ # `absolute` pair. Repeated calls with structurally equal arguments
22
+ # return the same object, so callers can rely on `equal?` for fast
23
+ # equality. The path Array is duplicated and frozen on insert.
24
+ def self.[](path, absolute)
25
+ absolute = absolute ? true : false
26
+
27
+ # Lock-free fast path.
28
+ node = absolute ? @intern_trie_absolute : @intern_trie_relative
29
+ path.each do |sym|
30
+ node = node[sym]
31
+ break unless node
32
+ end
33
+ if node && (cached = node[INTERN_LEAF])
34
+ return cached
35
+ end
36
+
37
+ @intern_mutex.synchronize do
38
+ node = absolute ? @intern_trie_absolute : @intern_trie_relative
39
+ path.each { |sym| node = (node[sym] ||= {}) }
40
+ node[INTERN_LEAF] ||= begin
41
+ frozen_path = path.frozen? ? path : path.dup.freeze
42
+ new(path: frozen_path, absolute: absolute)
43
+ end
44
+ end
45
+ end
46
+
12
47
  def self.empty
13
- @empty ||= new(path: [], absolute: false)
48
+ @empty ||= self[[], false]
14
49
  end
15
50
 
16
51
  def self.root
17
- @root ||= new(path: [], absolute: true)
52
+ @root ||= self[[], true]
18
53
  end
19
54
 
20
55
  def +(other)
21
56
  if other.absolute?
22
57
  other
23
58
  else
24
- self.class.new(path: path + other.path, absolute: absolute?)
59
+ Namespace[path + other.path, absolute?]
25
60
  end
26
61
  end
27
62
 
28
63
  def append(component)
29
- self.class.new(path: path + [component], absolute: absolute?)
64
+ Namespace[path + [component], absolute?]
30
65
  end
31
66
 
32
67
  def parent
33
68
  @parent ||= begin
34
69
  raise "Parent with empty namespace" if empty?
35
- self.class.new(path: path.take(path.size - 1), absolute: absolute?)
70
+ Namespace[path.take(path.size - 1), absolute?]
36
71
  end
37
72
  end
38
73
 
@@ -45,11 +80,11 @@ module RBS
45
80
  end
46
81
 
47
82
  def absolute!
48
- self.class.new(path: path, absolute: true)
83
+ Namespace[path, true]
49
84
  end
50
85
 
51
86
  def relative!
52
- self.class.new(path: path, absolute: false)
87
+ Namespace[path, false]
53
88
  end
54
89
 
55
90
  def empty?
@@ -57,13 +92,14 @@ module RBS
57
92
  end
58
93
 
59
94
  def ==(other)
95
+ return true if equal?(other)
60
96
  other.is_a?(Namespace) && other.path == path && other.absolute? == absolute?
61
97
  end
62
98
 
63
99
  alias eql? ==
64
100
 
65
101
  def hash
66
- path.hash ^ absolute?.hash
102
+ @hash ||= path.hash ^ absolute?.hash
67
103
  end
68
104
 
69
105
  def split
@@ -87,14 +123,14 @@ module RBS
87
123
  raise unless name
88
124
  raise unless parent
89
125
 
90
- TypeName.new(name: name, namespace: parent)
126
+ TypeName[parent, name]
91
127
  end
92
128
 
93
129
  def self.parse(string)
94
130
  if string.start_with?("::")
95
- new(path: string.split("::").drop(1).map(&:to_sym), absolute: true)
131
+ self[string.split("::").drop(1).map(&:to_sym), true]
96
132
  else
97
- new(path: string.split("::").map(&:to_sym), absolute: false)
133
+ self[string.split("::").map(&:to_sym), false]
98
134
  end
99
135
  end
100
136
 
@@ -121,12 +121,14 @@ module RBS
121
121
 
122
122
  def self.parse_inline_leading_annotation(source, range, variables: [])
123
123
  buf = buffer(source)
124
- _parse_inline_leading_annotation(buf, range.begin || 0, range.end || buf.last_position, variables)
124
+ byte_range = byte_range(range, buf.content)
125
+ _parse_inline_leading_annotation(buf, byte_range.begin || 0, byte_range.end || buf.content.bytesize, variables)
125
126
  end
126
127
 
127
128
  def self.parse_inline_trailing_annotation(source, range, variables: [])
128
129
  buf = buffer(source)
129
- _parse_inline_trailing_annotation(buf, range.begin || 0, range.end || buf.last_position, variables)
130
+ byte_range = byte_range(range, buf.content)
131
+ _parse_inline_trailing_annotation(buf, byte_range.begin || 0, byte_range.end || buf.content.bytesize, variables)
130
132
  end
131
133
 
132
134
  def self.byte_range(char_range, content)
@@ -9,10 +9,22 @@ module RBS
9
9
  attr_reader :modules
10
10
  attr_reader :last_sig
11
11
 
12
+ class Context
13
+ attr_accessor :singleton
14
+ attr_accessor :visibility
15
+
16
+ def initialize(singleton:, visibility:)
17
+ @singleton = singleton
18
+ @visibility = visibility
19
+ end
20
+ end
21
+
12
22
  def initialize
13
23
  @decls = []
14
24
 
15
25
  @modules = []
26
+ @contexts = []
27
+ @emitted_visibility = {}
16
28
  end
17
29
 
18
30
  def parse(string)
@@ -20,19 +32,17 @@ module RBS
20
32
  process RubyVM::AbstractSyntaxTree.parse(string), comments: comments
21
33
  end
22
34
 
23
- def nested_name(name)
24
- (current_namespace + const_to_name(name).to_namespace).to_type_name.relative!
25
- end
26
-
27
- def current_namespace
28
- modules.inject(Namespace.empty) do |parent, mod|
29
- parent + mod.name.to_namespace
35
+ def append_decl(decl)
36
+ if mod = current_module
37
+ mod.members << decl
38
+ else
39
+ decls << decl
30
40
  end
31
41
  end
32
42
 
33
43
  def push_class(name, super_class, comment:)
34
44
  class_decl = AST::Declarations::Class.new(
35
- name: nested_name(name),
45
+ name: const_to_name(name),
36
46
  super_class: super_class && AST::Declarations::Class::Super.new(name: const_to_name(super_class), args: [], location: nil),
37
47
  type_params: [],
38
48
  members: [],
@@ -41,17 +51,20 @@ module RBS
41
51
  comment: comment
42
52
  )
43
53
 
54
+ append_decl class_decl
44
55
  modules << class_decl
45
- decls << class_decl
56
+ @contexts << Context.new(singleton: false, visibility: :public)
57
+ @emitted_visibility[class_decl.object_id] = :public
46
58
 
47
59
  yield
48
60
  ensure
61
+ @contexts.pop
49
62
  modules.pop
50
63
  end
51
64
 
52
65
  def push_module(name, comment:)
53
66
  module_decl = AST::Declarations::Module.new(
54
- name: nested_name(name),
67
+ name: const_to_name(name),
55
68
  type_params: [],
56
69
  members: [],
57
70
  annotations: [],
@@ -60,11 +73,14 @@ module RBS
60
73
  comment: comment
61
74
  )
62
75
 
76
+ append_decl module_decl
63
77
  modules << module_decl
64
- decls << module_decl
78
+ @contexts << Context.new(singleton: false, visibility: :public)
79
+ @emitted_visibility[module_decl.object_id] = :public
65
80
 
66
81
  yield
67
82
  ensure
83
+ @contexts.pop
68
84
  modules.pop
69
85
  end
70
86
 
@@ -76,6 +92,47 @@ module RBS
76
92
  current_module or raise
77
93
  end
78
94
 
95
+ def current_context
96
+ @contexts.last
97
+ end
98
+
99
+ def current_context!
100
+ current_context or raise
101
+ end
102
+
103
+ # Visibility of a member, given as `private def ...` in RBS
104
+ #
105
+ # Returns `nil` for members in a visibility _section_, which `sync_visibility` emits instead.
106
+ def member_visibility(context)
107
+ # RBS visibility sections don't apply to singleton members, so they need their own visibility.
108
+ if context.singleton && context.visibility != :public
109
+ :private
110
+ end
111
+ end
112
+
113
+ def sync_visibility(visibility)
114
+ # Visibility sections don't apply to singleton members in RBS.
115
+ return if current_context!.singleton
116
+
117
+ # RBS has no protected visibility. Private is the conservative fallback.
118
+ visibility = :private if visibility == :protected
119
+
120
+ mod = current_module!
121
+ return if @emitted_visibility[mod.object_id] == visibility
122
+
123
+ member = case visibility
124
+ when :public
125
+ AST::Members::Public.new(location: nil)
126
+ when :private
127
+ AST::Members::Private.new(location: nil)
128
+ else
129
+ raise "Unexpected visibility: #{visibility}"
130
+ end
131
+
132
+ mod.members << member
133
+ @emitted_visibility[mod.object_id] = visibility
134
+ end
135
+
79
136
  def push_sig(node)
80
137
  if last_sig = @last_sig
81
138
  last_sig << node
@@ -107,6 +164,15 @@ module RBS
107
164
  push_module node.children[0], comment: comment do
108
165
  process node.children[1], outer: outer + [node], comments: comments
109
166
  end
167
+ when :SCLASS
168
+ if node.children[0].type == :SELF
169
+ @contexts << Context.new(singleton: true, visibility: :public)
170
+ begin
171
+ process node.children[1], outer: outer + [node], comments: comments
172
+ ensure
173
+ @contexts.pop
174
+ end
175
+ end
110
176
  when :FCALL
111
177
  case node.children[0]
112
178
  when :include
@@ -125,9 +191,9 @@ module RBS
125
191
  end
126
192
  when :extend
127
193
  each_arg node.children[1] do |arg|
128
- if arg.type == :CONST || arg.type == :COLON2
194
+ if arg.type == :CONST || arg.type == :COLON2 || arg.type == :COLON3
129
195
  name = const_to_name(arg)
130
- unless name.to_s == "T::Generic" || name.to_s == "T::Sig"
196
+ unless ["T::Generic", "T::Helpers", "T::Sig"].include?(name.to_s.delete_prefix("::"))
131
197
  member = AST::Members::Extend.new(
132
198
  name: name,
133
199
  args: [],
@@ -142,6 +208,10 @@ module RBS
142
208
  when :sig
143
209
  out = outer.last or raise
144
210
  push_sig out.children.last.children.last
211
+ when :attr_reader, :attr_writer, :attr_accessor
212
+ process_attribute node, comments: comments
213
+ when :private, :protected, :public
214
+ process_visibility node, outer: outer, comments: comments
145
215
  when :alias_method
146
216
  new, old = each_arg(node.children[1]).map {|x| x.children[0] }
147
217
  current_module!.members << AST::Members::Alias.new(
@@ -149,10 +219,15 @@ module RBS
149
219
  old_name: old,
150
220
  location: nil,
151
221
  annotations: [],
152
- kind: :instance,
222
+ kind: current_context!.singleton ? :singleton : :instance,
153
223
  comment: nil
154
224
  )
155
225
  end
226
+ when :VCALL
227
+ case node.children[0]
228
+ when :private, :protected, :public
229
+ current_context!.visibility = node.children[0]
230
+ end
156
231
  when :DEFS
157
232
  sigs = pop_sig
158
233
 
@@ -178,6 +253,8 @@ module RBS
178
253
  sigs = pop_sig
179
254
 
180
255
  if sigs
256
+ context = current_context!
257
+ sync_visibility(context.visibility)
181
258
  comment = join_comments(sigs, comments)
182
259
 
183
260
  args = node.children[1]
@@ -188,10 +265,10 @@ module RBS
188
265
  location: nil,
189
266
  annotations: [],
190
267
  overloads: types.map {|type| AST::Members::MethodDefinition::Overload.new(annotations: [], method_type: type) },
191
- kind: :instance,
268
+ kind: context.singleton ? :singleton : :instance,
192
269
  comment: comment,
193
270
  overloading: false,
194
- visibility: nil
271
+ visibility: member_visibility(context)
195
272
  )
196
273
  end
197
274
 
@@ -222,11 +299,7 @@ module RBS
222
299
  end
223
300
  else
224
301
  name = node.children[0].yield_self do |n|
225
- if n.is_a?(Symbol)
226
- TypeName.new(namespace: current_namespace, name: n)
227
- else
228
- const_to_name(n)
229
- end
302
+ n.is_a?(Symbol) ? TypeName.new(namespace: Namespace.empty, name: n) : const_to_name(n)
230
303
  end
231
304
  value_node = node.children.last
232
305
  type = if value_node && value_node.type == :CALL && value_node.children[1] == :let
@@ -235,7 +308,7 @@ module RBS
235
308
  else
236
309
  Types::Bases::Any.new(location: nil)
237
310
  end
238
- decls << AST::Declarations::Constant.new(
311
+ append_decl AST::Declarations::Constant.new(
239
312
  name: name,
240
313
  type: type,
241
314
  location: nil,
@@ -244,12 +317,13 @@ module RBS
244
317
  )
245
318
  end
246
319
  when :ALIAS
320
+ sync_visibility(current_context!.visibility)
247
321
  current_module!.members << AST::Members::Alias.new(
248
322
  new_name: node.children[0].children[0],
249
323
  old_name: node.children[1].children[0],
250
324
  location: nil,
251
325
  annotations: [],
252
- kind: :instance,
326
+ kind: current_context!.singleton ? :singleton : :instance,
253
327
  comment: nil
254
328
  )
255
329
  else
@@ -259,6 +333,93 @@ module RBS
259
333
  end
260
334
  end
261
335
 
336
+ def process_visibility(node, outer:, comments:)
337
+ visibility = node.children[0]
338
+ args = each_arg(node.children[1]).to_a
339
+ context = current_context!
340
+
341
+ if args.empty?
342
+ context.visibility = visibility
343
+ else
344
+ previous_visibility = context.visibility
345
+ context.visibility = visibility
346
+
347
+ begin
348
+ args.each do |arg|
349
+ if arg.type == :DEFN || arg.type == :DEFS
350
+ process arg, outer: outer + [node], comments: comments
351
+ end
352
+ end
353
+ ensure
354
+ context.visibility = previous_visibility
355
+ end
356
+ end
357
+ end
358
+
359
+ def process_attribute(node, comments:)
360
+ sigs = pop_sig
361
+ kind = node.children[0]
362
+ context = current_context!
363
+ sync_visibility(context.visibility)
364
+
365
+ type = attribute_type(kind, sigs)
366
+ comment = join_comments(sigs, comments) if sigs
367
+ member_class = case kind
368
+ when :attr_reader
369
+ AST::Members::AttrReader
370
+ when :attr_writer
371
+ AST::Members::AttrWriter
372
+ when :attr_accessor
373
+ AST::Members::AttrAccessor
374
+ else
375
+ raise "Unexpected attribute kind: #{kind}"
376
+ end
377
+
378
+ each_arg node.children[1] do |arg|
379
+ if name = symbol_literal_node?(arg)
380
+ current_module!.members << member_class.new(
381
+ name: name,
382
+ type: type,
383
+ ivar_name: nil,
384
+ kind: context.singleton ? :singleton : :instance,
385
+ annotations: [],
386
+ location: nil,
387
+ comment: comment,
388
+ visibility: member_visibility(context)
389
+ )
390
+ end
391
+ end
392
+ end
393
+
394
+ def attribute_type(kind, sigs)
395
+ any = Types::Bases::Any.new(location: nil)
396
+ return any unless sigs
397
+
398
+ method_types = sigs.filter_map do |sig|
399
+ method_type(nil, sig, variables: current_module!.type_params, overloads: sigs.size)
400
+ end
401
+ function = method_types.last&.type
402
+ return any unless function.is_a?(Types::Function)
403
+
404
+ parameter_type = function.required_positionals.first&.type
405
+ return_type = function.return_type
406
+
407
+ case kind
408
+ when :attr_reader
409
+ return_type
410
+ when :attr_writer
411
+ parameter_type || return_type
412
+ when :attr_accessor
413
+ if return_type.is_a?(Types::Bases::Any) || return_type.is_a?(Types::Bases::Void)
414
+ parameter_type || any
415
+ else
416
+ return_type
417
+ end
418
+ else
419
+ any
420
+ end
421
+ end
422
+
262
423
  def method_type(args_node, type_node, variables:, overloads:)
263
424
  if type_node
264
425
  if type_node.type == :CALL
@@ -463,8 +624,10 @@ module RBS
463
624
  case
464
625
  when type.is_a?(Types::ClassInstance) && type.name.name == BuiltinNames::BasicObject.name.name
465
626
  Types::Bases::Any.new(location: nil)
466
- when type.is_a?(Types::ClassInstance) && type.name.to_s == "T::Boolean"
627
+ when type.is_a?(Types::ClassInstance) && type.name.to_s.delete_prefix("::") == "T::Boolean"
467
628
  Types::Bases::Bool.new(location: nil)
629
+ when type.is_a?(Types::ClassInstance) && type.name.to_s.delete_prefix("::") == "T::Class"
630
+ Types::Bases::Any.new(location: nil)
468
631
  else
469
632
  type
470
633
  end
@@ -482,6 +645,11 @@ module RBS
482
645
  Types::ClassInstance.new(name: const_to_name(type_node), args: [], location: nil)
483
646
  when call_node?(type_node, name: :[], receiver: -> (_) { true })
484
647
  # The type_node represents a type application
648
+ receiver = type_node.children[0]
649
+ if [:CONST, :COLON2, :COLON3].include?(receiver.type) && const_to_name(receiver).to_s.delete_prefix("::") == "T::Class"
650
+ return Types::Bases::Any.new(location: nil)
651
+ end
652
+
485
653
  type = type_of(type_node.children[0], variables: variables)
486
654
  type.is_a?(Types::ClassInstance) or raise
487
655
 
@@ -559,7 +727,7 @@ module RBS
559
727
 
560
728
  type_name = TypeName.new(name: node.children[1], namespace: namespace)
561
729
 
562
- case type_name.to_s
730
+ case type_name.to_s.delete_prefix("::")
563
731
  when "T::Array"
564
732
  BuiltinNames::Array.name
565
733
  when "T::Hash"
@@ -77,6 +77,8 @@ module RBS
77
77
  attr_accessor :outline
78
78
 
79
79
  def initialize(patterns:, env:, merge:, todo: false, owners_included: [])
80
+ Kernel.warn("RBS::Prototype::Runtime is deprecated. See https://github.com/ruby/rbs/issues/2841")
81
+
80
82
  @patterns = patterns
81
83
  @decls = nil
82
84
  @modules = {}