rbs 0.16.0 → 0.20.0

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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +1 -1
  3. data/CHANGELOG.md +30 -0
  4. data/README.md +1 -1
  5. data/Rakefile +12 -1
  6. data/core/array.rbs +1 -1
  7. data/core/builtin.rbs +2 -2
  8. data/core/dir.rbs +1 -1
  9. data/core/enumerable.rbs +41 -40
  10. data/core/enumerator.rbs +5 -5
  11. data/core/file.rbs +0 -4
  12. data/core/hash.rbs +9 -11
  13. data/core/io.rbs +1 -1
  14. data/core/object_space.rbs +98 -0
  15. data/core/range.rbs +1 -1
  16. data/core/struct.rbs +1 -1
  17. data/core/time.rbs +0 -12
  18. data/lib/rbs/ast/members.rb +9 -3
  19. data/lib/rbs/definition.rb +9 -4
  20. data/lib/rbs/definition_builder.rb +123 -71
  21. data/lib/rbs/environment.rb +3 -0
  22. data/lib/rbs/environment_loader.rb +1 -1
  23. data/lib/rbs/environment_walker.rb +70 -35
  24. data/lib/rbs/method_type.rb +1 -31
  25. data/lib/rbs/parser.rb +944 -879
  26. data/lib/rbs/parser.y +110 -63
  27. data/lib/rbs/prototype/rb.rb +163 -23
  28. data/lib/rbs/prototype/rbi.rb +5 -5
  29. data/lib/rbs/prototype/runtime.rb +2 -1
  30. data/lib/rbs/test/hook.rb +30 -17
  31. data/lib/rbs/test/type_check.rb +6 -1
  32. data/lib/rbs/types.rb +63 -6
  33. data/lib/rbs/version.rb +1 -1
  34. data/lib/rbs/writer.rb +9 -1
  35. data/schema/members.json +5 -1
  36. data/sig/definition.rbs +8 -3
  37. data/sig/definition_builder.rbs +6 -2
  38. data/sig/members.rbs +4 -1
  39. data/sig/method_types.rbs +3 -16
  40. data/sig/types.rbs +17 -1
  41. data/stdlib/csv/0/csv.rbs +3 -3
  42. data/stdlib/dbm/0/dbm.rbs +1 -3
  43. data/stdlib/monitor/0/monitor.rbs +119 -0
  44. data/stdlib/prime/0/prime.rbs +1 -1
  45. data/stdlib/set/0/set.rbs +10 -10
  46. data/stdlib/singleton/0/singleton.rbs +111 -0
  47. data/stdlib/tsort/0/cyclic.rbs +4 -0
  48. data/stdlib/tsort/0/interfaces.rbs +19 -0
  49. data/stdlib/tsort/0/tsort.rbs +371 -0
  50. data/stdlib/yaml/0/dbm.rbs +221 -0
  51. data/stdlib/yaml/0/store.rbs +53 -0
  52. data/steep/Gemfile.lock +12 -12
  53. metadata +11 -3
@@ -20,7 +20,7 @@ class RBS::Parser
20
20
  nonassoc kARROW
21
21
  preclow
22
22
 
23
- expect 2
23
+ expect 5
24
24
 
25
25
  rule
26
26
 
@@ -202,57 +202,67 @@ rule
202
202
  | alias_member
203
203
  | signature
204
204
 
205
+ attribute_kind:
206
+ { result = :instance }
207
+ | kSELF kDOT { result = :singleton }
208
+
205
209
  attribute_member:
206
- annotations kATTRREADER keyword type {
207
- location = val[1].location + val[3].location
208
- result = Members::AttrReader.new(name: val[2].value,
210
+ annotations kATTRREADER attribute_kind keyword type {
211
+ location = val[1].location + val[4].location
212
+ result = Members::AttrReader.new(name: val[3].value,
209
213
  ivar_name: nil,
210
- type: val[3],
214
+ type: val[4],
215
+ kind: val[2],
211
216
  annotations: val[0],
212
217
  location: location,
213
218
  comment: leading_comment(val[0].first&.location || location))
214
219
  }
215
- | annotations kATTRREADER method_name attr_var_opt kCOLON type {
216
- location = val[1].location + val[5].location
217
- result = Members::AttrReader.new(name: val[2].value.to_sym,
218
- ivar_name: val[3],
219
- type: val[5],
220
+ | annotations kATTRREADER attribute_kind method_name attr_var_opt kCOLON type {
221
+ location = val[1].location + val[6].location
222
+ result = Members::AttrReader.new(name: val[3].value.to_sym,
223
+ ivar_name: val[4],
224
+ type: val[6],
225
+ kind: val[2],
220
226
  annotations: val[0],
221
227
  location: location,
222
228
  comment: leading_comment(val[0].first&.location || location))
223
229
  }
224
- | annotations kATTRWRITER keyword type {
225
- location = val[1].location + val[3].location
226
- result = Members::AttrWriter.new(name: val[2].value,
230
+ | annotations kATTRWRITER attribute_kind keyword type {
231
+ location = val[1].location + val[4].location
232
+ result = Members::AttrWriter.new(name: val[3].value,
227
233
  ivar_name: nil,
228
- type: val[3],
234
+ kind: val[2],
235
+ type: val[4],
229
236
  annotations: val[0],
230
237
  location: location,
231
238
  comment: leading_comment(val[0].first&.location || location))
232
239
  }
233
- | annotations kATTRWRITER method_name attr_var_opt kCOLON type {
234
- location = val[1].location + val[5].location
235
- result = Members::AttrWriter.new(name: val[2].value.to_sym,
236
- ivar_name: val[3],
237
- type: val[5],
240
+ | annotations kATTRWRITER attribute_kind method_name attr_var_opt kCOLON type {
241
+ location = val[1].location + val[6].location
242
+ result = Members::AttrWriter.new(name: val[3].value.to_sym,
243
+ ivar_name: val[4],
244
+ kind: val[2],
245
+ type: val[6],
238
246
  annotations: val[0],
239
247
  location: location,
240
248
  comment: leading_comment(val[0].first&.location || location))
241
249
  }
242
- | annotations kATTRACCESSOR keyword type {
243
- location = val[1].location + val[3].location
244
- result = Members::AttrAccessor.new(name: val[2].value,
250
+ | annotations kATTRACCESSOR attribute_kind keyword type {
251
+ location = val[1].location + val[4].location
252
+ result = Members::AttrAccessor.new(name: val[3].value,
245
253
  ivar_name: nil,
246
- type: val[3],
254
+ kind: val[2],
255
+ type: val[4],
247
256
  annotations: val[0],
248
257
  location: location,
249
258
  comment: leading_comment(val[0].first&.location || location))
250
259
  }
251
- | annotations kATTRACCESSOR method_name attr_var_opt kCOLON type {
252
- location = val[1].location + val[5].location
253
- result = Members::AttrAccessor.new(name: val[2].value.to_sym,
254
- ivar_name: val[3],
255
- type: val[5],
260
+ | annotations kATTRACCESSOR attribute_kind method_name attr_var_opt kCOLON type {
261
+ location = val[1].location + val[6].location
262
+ result = Members::AttrAccessor.new(name: val[3].value.to_sym,
263
+ ivar_name: val[4],
264
+ kind: val[2],
265
+ type: val[6],
256
266
  annotations: val[0],
257
267
  location: location,
258
268
  comment: leading_comment(val[0].first&.location || location))
@@ -474,26 +484,13 @@ rule
474
484
  }
475
485
 
476
486
  method_type:
477
- start_merged_scope type_params params_opt block_opt kARROW simple_type {
487
+ start_merged_scope type_params proc_type {
478
488
  reset_variable_scope
479
489
 
480
- location = (val[1] || val[2] || val[3] || val[4]).location + val[5].location
490
+ location = (val[1] || val[2]).location + val[2].location
481
491
  type_params = val[1]&.value || []
482
492
 
483
- params = val[2]&.value || empty_params_result
484
-
485
- type = Types::Function.new(
486
- required_positionals: params[0],
487
- optional_positionals: params[1],
488
- rest_positionals: params[2],
489
- trailing_positionals: params[3],
490
- required_keywords: params[4],
491
- optional_keywords: params[5],
492
- rest_keywords: params[6],
493
- return_type: val[5]
494
- )
495
-
496
- block = val[3]&.value
493
+ type, block = val[2].value
497
494
 
498
495
  result = MethodType.new(type_params: type_params,
499
496
  type: type,
@@ -507,14 +504,13 @@ rule
507
504
  result = LocatedValue.new(value: val[1], location: val[0].location + val[2].location)
508
505
  }
509
506
 
510
- block_opt:
511
- { result = nil }
512
- | kLBRACE function_type kRBRACE {
513
- block = MethodType::Block.new(type: val[1].value, required: true)
507
+ block:
508
+ kLBRACE simple_function_type kRBRACE {
509
+ block = Types::Block.new(type: val[1].value, required: true)
514
510
  result = LocatedValue.new(value: block, location: val[0].location + val[2].location)
515
511
  }
516
- | kQUESTION kLBRACE function_type kRBRACE {
517
- block = MethodType::Block.new(type: val[2].value, required: false)
512
+ | kQUESTION kLBRACE simple_function_type kRBRACE {
513
+ block = Types::Block.new(type: val[2].value, required: false)
518
514
  result = LocatedValue.new(value: block, location: val[0].location + val[3].location)
519
515
  }
520
516
 
@@ -797,8 +793,9 @@ rule
797
793
  result = Types::ClassSingleton.new(name: val[2].value,
798
794
  location: val[0].location + val[3].location)
799
795
  }
800
- | kHAT function_type {
801
- result = Types::Proc.new(type: val[1].value, location: val[0].location + val[1].location)
796
+ | kHAT proc_type {
797
+ type, block = val[1].value
798
+ result = Types::Proc.new(type: type, block: block, location: val[0].location + val[1].location)
802
799
  }
803
800
  | simple_type kQUESTION {
804
801
  result = Types::Optional.new(type: val[0], location: val[0].location + val[1].location)
@@ -851,7 +848,32 @@ rule
851
848
 
852
849
  keyword: tLKEYWORD | tUKEYWORD | tLKEYWORD_Q_E | tUKEYWORD_Q_E
853
850
 
854
- function_type:
851
+ proc_type:
852
+ params_opt block kARROW simple_type {
853
+ location = (val[0] || val[1] || val[2]).location + val[3].location
854
+
855
+ params = val[0]&.value || [[], [], nil, [], {}, {}, nil]
856
+
857
+ type = Types::Function.new(
858
+ required_positionals: params[0],
859
+ optional_positionals: params[1],
860
+ rest_positionals: params[2],
861
+ trailing_positionals: params[3],
862
+ required_keywords: params[4],
863
+ optional_keywords: params[5],
864
+ rest_keywords: params[6],
865
+ return_type: val[3]
866
+ )
867
+
868
+ block = val[1].value
869
+
870
+ result = LocatedValue.new(value: [type, block], location: location)
871
+ }
872
+ | simple_function_type {
873
+ result = LocatedValue.new(value: [val[0].value, nil], location: val[0].location)
874
+ }
875
+
876
+ simple_function_type:
855
877
  kLPAREN params kRPAREN kARROW simple_type {
856
878
  location = val[0].location + val[4].location
857
879
  type = Types::Function.new(
@@ -883,7 +905,7 @@ rule
883
905
  result = LocatedValue.new(value: type, location: location)
884
906
  }
885
907
 
886
- params:
908
+ params:
887
909
  required_positional kCOMMA params {
888
910
  result = val[2]
889
911
  result[0].unshift(val[0])
@@ -1168,14 +1190,21 @@ end
1168
1190
 
1169
1191
  def new_token(type, value = input.matched)
1170
1192
  charpos = charpos(input)
1171
- start_index = charpos - input.matched.size
1172
- end_index = charpos
1193
+ matched = input.matched
1194
+
1195
+ if matched
1196
+ start_index = charpos - matched.size
1197
+ end_index = charpos
1173
1198
 
1174
- location = RBS::Location.new(buffer: buffer,
1175
- start_pos: start_index,
1176
- end_pos: end_index)
1199
+ location = RBS::Location.new(buffer: buffer,
1200
+ start_pos: start_index,
1201
+ end_pos: end_index)
1177
1202
 
1178
- [type, LocatedValue.new(location: location, value: value)]
1203
+ [type, LocatedValue.new(location: location, value: value)]
1204
+ else
1205
+ # scanner hasn't matched yet
1206
+ [false, nil]
1207
+ end
1179
1208
  end
1180
1209
 
1181
1210
  def charpos(scanner)
@@ -1287,6 +1316,10 @@ ANNOTATION_RE = Regexp.union(/%a\{.*?\}/,
1287
1316
  /%a\(.*?\)/,
1288
1317
  /%a\<.*?\>/,
1289
1318
  /%a\|.*?\|/)
1319
+
1320
+ escape_sequences = %w[a b e f n r s t v "].map { |l| "\\\\#{l}" }
1321
+ DBL_QUOTE_STR_ESCAPE_SEQUENCES_RE = /(#{escape_sequences.join("|")})/
1322
+
1290
1323
  def next_token
1291
1324
  if @type
1292
1325
  type = @type
@@ -1294,10 +1327,10 @@ def next_token
1294
1327
  return [:"type_#{type}", nil]
1295
1328
  end
1296
1329
 
1297
- return if @eof
1330
+ return new_token(false, '') if @eof
1298
1331
 
1299
1332
  while true
1300
- return if input.eos?
1333
+ return new_token(false, '') if input.eos?
1301
1334
 
1302
1335
  case
1303
1336
  when input.scan(/\s+/)
@@ -1366,7 +1399,21 @@ def next_token
1366
1399
  when input.scan(/[a-z_]\w*\b/)
1367
1400
  new_token(:tLIDENT)
1368
1401
  when input.scan(/"(\\"|[^"])*"/)
1369
- s = input.matched.yield_self {|s| s[1, s.length - 2] }.gsub(/\\"/, '"')
1402
+ s = input.matched.yield_self {|s| s[1, s.length - 2] }
1403
+ .gsub(DBL_QUOTE_STR_ESCAPE_SEQUENCES_RE) do |match|
1404
+ case match
1405
+ when '\\a' then "\a"
1406
+ when '\\b' then "\b"
1407
+ when '\\e' then "\e"
1408
+ when '\\f' then "\f"
1409
+ when '\\n' then "\n"
1410
+ when '\\r' then "\r"
1411
+ when '\\s' then "\s"
1412
+ when '\\t' then "\t"
1413
+ when '\\v' then "\v"
1414
+ when '\\"' then '"'
1415
+ end
1416
+ end
1370
1417
  new_token(:tSTRING, s)
1371
1418
  when input.scan(/'(\\'|[^'])*'/)
1372
1419
  s = input.matched.yield_self {|s| s[1, s.length - 2] }.gsub(/\\'/, "'")
@@ -1,6 +1,30 @@
1
1
  module RBS
2
2
  module Prototype
3
3
  class RB
4
+ Context = Struct.new(:module_function, :singleton, :namespace, keyword_init: true) do
5
+ def self.initial(namespace: Namespace.root)
6
+ self.new(module_function: false, singleton: false, namespace: namespace)
7
+ end
8
+
9
+ def method_kind
10
+ if singleton
11
+ :singleton
12
+ elsif module_function
13
+ :singleton_instance
14
+ else
15
+ :instance
16
+ end
17
+ end
18
+
19
+ def attribute_kind
20
+ if singleton
21
+ :singleton
22
+ else
23
+ :instance
24
+ end
25
+ end
26
+ end
27
+
4
28
  attr_reader :source_decls
5
29
  attr_reader :toplevel_members
6
30
 
@@ -52,10 +76,10 @@ module RBS
52
76
  end
53
77
  end
54
78
 
55
- process RubyVM::AbstractSyntaxTree.parse(string), decls: source_decls, comments: comments, singleton: false
79
+ process RubyVM::AbstractSyntaxTree.parse(string), decls: source_decls, comments: comments, context: Context.initial
56
80
  end
57
81
 
58
- def process(node, decls:, comments:, singleton:)
82
+ def process(node, decls:, comments:, context:)
59
83
  case node.type
60
84
  when :CLASS
61
85
  class_name, super_class, *class_body = node.children
@@ -71,9 +95,11 @@ module RBS
71
95
 
72
96
  decls.push kls
73
97
 
98
+ new_ctx = Context.initial(namespace: context.namespace + kls.name.to_namespace)
74
99
  each_node class_body do |child|
75
- process child, decls: kls.members, comments: comments, singleton: false
100
+ process child, decls: kls.members, comments: comments, context: new_ctx
76
101
  end
102
+ remove_unnecessary_accessibility_methods! kls.members
77
103
 
78
104
  when :MODULE
79
105
  module_name, *module_body = node.children
@@ -90,9 +116,11 @@ module RBS
90
116
 
91
117
  decls.push mod
92
118
 
119
+ new_ctx = Context.initial(namespace: context.namespace + mod.name.to_namespace)
93
120
  each_node module_body do |child|
94
- process child, decls: mod.members, comments: comments, singleton: false
121
+ process child, decls: mod.members, comments: comments, context: new_ctx
95
122
  end
123
+ remove_unnecessary_accessibility_methods! mod.members
96
124
 
97
125
  when :SCLASS
98
126
  this, body = node.children
@@ -101,14 +129,13 @@ module RBS
101
129
  RBS.logger.warn "`class <<` syntax with not-self may be compiled to incorrect code: #{this}"
102
130
  end
103
131
 
104
- each_child(body) do |child|
105
- process child, decls: decls, comments: comments, singleton: true
106
- end
132
+ ctx = Context.initial.tap { |ctx| ctx.singleton = true }
133
+ process_children(body, decls: decls, comments: comments, context: ctx)
107
134
 
108
135
  when :DEFN, :DEFS
109
136
  if node.type == :DEFN
110
137
  def_name, def_body = node.children
111
- kind = singleton ? :singleton : :instance
138
+ kind = context.method_kind
112
139
  else
113
140
  _, def_name, def_body = node.children
114
141
  kind = :singleton
@@ -140,14 +167,14 @@ module RBS
140
167
  member = AST::Members::Alias.new(
141
168
  new_name: new_name,
142
169
  old_name: old_name,
143
- kind: singleton ? :singleton : :instance,
170
+ kind: context.singleton ? :singleton : :instance,
144
171
  annotations: [],
145
172
  location: nil,
146
173
  comment: comments[node.first_lineno - 1],
147
174
  )
148
175
  decls.push member unless decls.include?(member)
149
176
 
150
- when :FCALL
177
+ when :FCALL, :VCALL
151
178
  # Inside method definition cannot reach here.
152
179
  args = node.children[1]&.children || []
153
180
 
@@ -166,7 +193,7 @@ module RBS
166
193
  end
167
194
  when :extend
168
195
  args.each do |arg|
169
- if (name = const_to_name(arg))
196
+ if (name = const_to_name(arg, context: context))
170
197
  decls << AST::Members::Extend.new(
171
198
  name: name,
172
199
  args: [],
@@ -183,6 +210,7 @@ module RBS
183
210
  name: name,
184
211
  ivar_name: nil,
185
212
  type: Types::Bases::Any.new(location: nil),
213
+ kind: context.attribute_kind,
186
214
  location: nil,
187
215
  comment: comments[node.first_lineno - 1],
188
216
  annotations: []
@@ -196,6 +224,7 @@ module RBS
196
224
  name: name,
197
225
  ivar_name: nil,
198
226
  type: Types::Bases::Any.new(location: nil),
227
+ kind: context.attribute_kind,
199
228
  location: nil,
200
229
  comment: comments[node.first_lineno - 1],
201
230
  annotations: []
@@ -209,6 +238,7 @@ module RBS
209
238
  name: name,
210
239
  ivar_name: nil,
211
240
  type: Types::Bases::Any.new(location: nil),
241
+ kind: context.attribute_kind,
212
242
  location: nil,
213
243
  comment: comments[node.first_lineno - 1],
214
244
  annotations: []
@@ -220,16 +250,61 @@ module RBS
220
250
  decls << AST::Members::Alias.new(
221
251
  new_name: new_name,
222
252
  old_name: old_name,
223
- kind: singleton ? :singleton : :instance,
253
+ kind: context.singleton ? :singleton : :instance,
224
254
  annotations: [],
225
255
  location: nil,
226
256
  comment: comments[node.first_lineno - 1],
227
257
  )
228
258
  end
259
+ when :module_function
260
+ if args.empty?
261
+ context.module_function = true
262
+ else
263
+ module_func_context = context.dup.tap { |ctx| ctx.module_function = true }
264
+ args.each do |arg|
265
+ if arg && (name = literal_to_symbol(arg))
266
+ if i = find_def_index_by_name(decls, name)
267
+ decls[i] = decls[i].update(kind: :singleton_instance)
268
+ end
269
+ elsif arg
270
+ process arg, decls: decls, comments: comments, context: module_func_context
271
+ end
272
+ end
273
+ end
274
+ when :public, :private
275
+ accessibility = __send__(node.children[0])
276
+ if args.empty?
277
+ decls << accessibility
278
+ else
279
+ args.each do |arg|
280
+ if arg && (name = literal_to_symbol(arg))
281
+ if i = find_def_index_by_name(decls, name)
282
+ current = current_accessibility(decls, i)
283
+ if current != accessibility
284
+ decls.insert(i + 1, current)
285
+ decls.insert(i, accessibility)
286
+ end
287
+ end
288
+ end
289
+ end
290
+
291
+ # For `private def foo` syntax
292
+ current = current_accessibility(decls)
293
+ decls << accessibility
294
+ process_children(node, decls: decls, comments: comments, context: context)
295
+ decls << current
296
+ end
297
+ else
298
+ process_children(node, decls: decls, comments: comments, context: context)
229
299
  end
230
300
 
231
- each_child node do |child|
232
- process child, decls: decls, comments: comments, singleton: singleton
301
+ when :ITER
302
+ method_name = node.children.first.children.first
303
+ case method_name
304
+ when :refine
305
+ # ignore
306
+ else
307
+ process_children(node, decls: decls, comments: comments, context: context)
233
308
  end
234
309
 
235
310
  when :CDECL
@@ -248,13 +323,17 @@ module RBS
248
323
  )
249
324
 
250
325
  else
251
- each_child node do |child|
252
- process child, decls: decls, comments: comments, singleton: singleton
253
- end
326
+ process_children(node, decls: decls, comments: comments, context: context)
254
327
  end
255
328
  end
256
329
 
257
- def const_to_name(node)
330
+ def process_children(node, decls:, comments:, context:)
331
+ each_child node do |child|
332
+ process child, decls: decls, comments: comments, context: context
333
+ end
334
+ end
335
+
336
+ def const_to_name(node, context: nil)
258
337
  case node&.type
259
338
  when :CONST
260
339
  TypeName.new(name: node.children[0], namespace: Namespace.empty)
@@ -268,6 +347,8 @@ module RBS
268
347
  TypeName.new(name: node.children[1], namespace: namespace)
269
348
  when :COLON3
270
349
  TypeName.new(name: node.children[0], namespace: Namespace.root)
350
+ when :SELF
351
+ context&.then { |c| c.namespace.to_type_name }
271
352
  end
272
353
  end
273
354
 
@@ -411,7 +492,8 @@ module RBS
411
492
  when :HASH
412
493
  list = node.children[0]
413
494
  if list
414
- children = list.children.compact
495
+ children = list.children
496
+ children.pop
415
497
  else
416
498
  children = []
417
499
  end
@@ -419,8 +501,13 @@ module RBS
419
501
  key_types = []
420
502
  value_types = []
421
503
  children.each_slice(2) do |k, v|
422
- key_types << literal_to_type(k)
423
- value_types << literal_to_type(v)
504
+ if k
505
+ key_types << literal_to_type(k)
506
+ value_types << literal_to_type(v)
507
+ else
508
+ key_types << untyped
509
+ value_types << untyped
510
+ end
424
511
  end
425
512
 
426
513
  if !key_types.empty? && key_types.all? { |t| t.is_a?(Types::Literal) }
@@ -473,7 +560,7 @@ module RBS
473
560
  method_block = nil
474
561
 
475
562
  if block
476
- method_block = MethodType::Block.new(
563
+ method_block = Types::Block.new(
477
564
  required: true,
478
565
  type: Types::Function.empty(untyped)
479
566
  )
@@ -481,7 +568,7 @@ module RBS
481
568
 
482
569
  if body_node
483
570
  if (yields = any_node?(body_node) {|n| n.type == :YIELD })
484
- method_block = MethodType::Block.new(
571
+ method_block = Types::Block.new(
485
572
  required: true,
486
573
  type: Types::Function.empty(untyped)
487
574
  )
@@ -580,6 +667,59 @@ module RBS
580
667
  def untyped
581
668
  @untyped ||= Types::Bases::Any.new(location: nil)
582
669
  end
670
+
671
+ def private
672
+ @private ||= AST::Members::Private.new(location: nil)
673
+ end
674
+
675
+ def public
676
+ @public ||= AST::Members::Public.new(location: nil)
677
+ end
678
+
679
+ def current_accessibility(decls, index = decls.size)
680
+ idx = decls.slice(0, index).rindex { |decl| decl == private || decl == public }
681
+ (idx && decls[idx]) || public
682
+ end
683
+
684
+ def remove_unnecessary_accessibility_methods!(decls)
685
+ current = public
686
+ idx = 0
687
+
688
+ loop do
689
+ decl = decls[idx] or break
690
+ if current == decl
691
+ decls.delete_at(idx)
692
+ next
693
+ end
694
+
695
+ if 0 < idx && is_accessibility?(decls[idx - 1]) && is_accessibility?(decl)
696
+ decls.delete_at(idx - 1)
697
+ idx -= 1
698
+ current = current_accessibility(decls, idx)
699
+ next
700
+ end
701
+
702
+ current = decl if is_accessibility?(decl)
703
+ idx += 1
704
+ end
705
+
706
+ decls.pop while decls.last && is_accessibility?(decls.last)
707
+ end
708
+
709
+ def is_accessibility?(decl)
710
+ decl == public || decl == private
711
+ end
712
+
713
+ def find_def_index_by_name(decls, name)
714
+ decls.find_index do |decl|
715
+ case decl
716
+ when AST::Members::MethodDefinition, AST::Members::AttrReader
717
+ decl.name == name
718
+ when AST::Members::AttrWriter
719
+ decl.name == :"#{name}="
720
+ end
721
+ end
722
+ end
583
723
  end
584
724
  end
585
725
  end