rbs 0.17.0 → 0.18.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f458be96f0cfc3e45e51bb77f4d42aafba7f1fee62e0ed8695eb6a95b85189b2
4
- data.tar.gz: 9b84c8860182155f4e5979e668a953d1b8191754f01c6443d549fc14b5be1908
3
+ metadata.gz: 809717411a8c5922fa704c952333218bfb14ab4eef9e162c26d5d905de9009a2
4
+ data.tar.gz: 93d8af500d84269a6ea5d5631538de69d01633276a0860002c7bd63e3ae05ace
5
5
  SHA512:
6
- metadata.gz: f0c7616abdb3a3d4e08212014aebad858e113acf265641e4f657b2d48b9e20ec8ac7744a18f90459086be39953eb7ebef9d32acd3b22362e31d6e12e83251baf
7
- data.tar.gz: ee12553e0611d2b8826d9687ab63fcc38bfb67435bcf537950b31ef6070c26d85fcf8d956ccc1285072e6513facdbd43521935ae9372a11cae6f100e16691084
6
+ metadata.gz: b8109ce0129574ed1752291a4c541d99c2738bb238d16bf1bd153123181386eb461075a3ecb68502191bdadb8d09b1501b68aa2f45fc39cbac7febbed13f28b2
7
+ data.tar.gz: cbeca49f8e35b2ecf9ac32a11b7389c30da90418594e840ee50c2cf276470d37eee0d2d615169fed5b0c89daf00216d4e5c78d5ff310e455729fbe435e917bf3
@@ -2,6 +2,14 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 0.18.0 (2020-12-01)
6
+
7
+ * Signature updates for `YAML`, `ObjectSpace`, and `Singleton` ([#408](https://github.com/ruby/rbs/pull/408), [#477](https://github.com/ruby/rbs/pull/477), [#482](https://github.com/ruby/rbs/pull/482))
8
+ * `prototype rb` improvements ([#492](https://github.com/ruby/rbs/pull/492), [#487](https://github.com/ruby/rbs/pull/487), [#486](https://github.com/ruby/rbs/pull/486), [#481](https://github.com/ruby/rbs/pull/481))
9
+ * Runtime type checker improvements ([#488](https://github.com/ruby/rbs/pull/488), [#489](https://github.com/ruby/rbs/pull/489), [#490](https://github.com/ruby/rbs/pull/490))
10
+ * Update `DependencyWalker` API to receive _Node_ objects instead of `TypeName` ([#484](https://github.com/ruby/rbs/pull/484))
11
+ * Assume encoding of RBS files to be UTF-8 ([#493](https://github.com/ruby/rbs/pull/493))
12
+
5
13
  ## 0.17.0 (2020-11-14)
6
14
 
7
15
  * Signature updates for `Enumerable`, `Hash`, and `TSort` ([#462](https://github.com/ruby/rbs/pull/462), [#468](https://github.com/ruby/rbs/pull/468), [#471](https://github.com/ruby/rbs/pull/471), [#472](https://github.com/ruby/rbs/pull/472), [#473](https://github.com/ruby/rbs/pull/473), [#474](https://github.com/ruby/rbs/pull/474))
data/Rakefile CHANGED
@@ -36,6 +36,11 @@ task :validate => :parser do
36
36
  lib << "bigdecimal"
37
37
  end
38
38
 
39
+ if lib == ["yaml"]
40
+ lib << "dbm"
41
+ lib << "pstore"
42
+ end
43
+
39
44
  sh "#{ruby} #{rbs} #{lib.map {|l| "-r #{l}"}.join(" ")} validate --silent"
40
45
  end
41
46
  end
@@ -0,0 +1,98 @@
1
+ # The ObjectSpace module contains a number of routines that interact with the
2
+ # garbage collection facility and allow you to traverse all living objects with
3
+ # an iterator.
4
+ #
5
+ # ObjectSpace also provides support for object finalizers, procs that will be
6
+ # called when a specific object is about to be destroyed by garbage collection.
7
+ #
8
+ # require 'objspace'
9
+ #
10
+ # a = "A"
11
+ # b = "B"
12
+ #
13
+ # ObjectSpace.define_finalizer(a, proc {|id| puts "Finalizer one on #{id}" })
14
+ # ObjectSpace.define_finalizer(b, proc {|id| puts "Finalizer two on #{id}" })
15
+ #
16
+ # *produces:*
17
+ #
18
+ # Finalizer two on 537763470
19
+ # Finalizer one on 537763480
20
+ module ObjectSpace
21
+ def self._id2ref: (Integer id) -> untyped
22
+
23
+ # Counts all objects grouped by type.
24
+ #
25
+ # It returns a hash, such as:
26
+ # {
27
+ # :TOTAL=>10000,
28
+ # :FREE=>3011,
29
+ # :T_OBJECT=>6,
30
+ # :T_CLASS=>404,
31
+ # # ...
32
+ # }
33
+ #
34
+ # The contents of the returned hash are implementation specific. It may be
35
+ # changed in future.
36
+ #
37
+ # The keys starting with `:T_` means live objects. For example, `:T_ARRAY` is
38
+ # the number of arrays. `:FREE` means object slots which is not used now.
39
+ # `:TOTAL` means sum of above.
40
+ #
41
+ # If the optional argument `result_hash` is given, it is overwritten and
42
+ # returned. This is intended to avoid probe effect.
43
+ #
44
+ # h = {}
45
+ # ObjectSpace.count_objects(h)
46
+ # puts h
47
+ # # => { :TOTAL=>10000, :T_CLASS=>158280, :T_MODULE=>20672, :T_STRING=>527249 }
48
+ #
49
+ # This method is only expected to work on C Ruby.
50
+ #
51
+ def self.count_objects: (?Hash[Symbol, Integer] result_hash) -> Hash[Symbol, Integer]
52
+
53
+ # Adds *aProc* as a finalizer, to be called after *obj* was destroyed. The
54
+ # object ID of the *obj* will be passed as an argument to *aProc*. If *aProc* is
55
+ # a lambda or method, make sure it can be called with a single argument.
56
+ #
57
+ def self.define_finalizer: (untyped obj, ^(Integer id) -> void aProc) -> [ Integer, Proc ]
58
+ | (untyped obj) { (Integer id) -> void } -> [ Integer, Proc ]
59
+
60
+ # Calls the block once for each living, nonimmediate object in this Ruby
61
+ # process. If *module* is specified, calls the block for only those classes or
62
+ # modules that match (or are a subclass of) *module*. Returns the number of
63
+ # objects found. Immediate objects (`Fixnum`s, `Symbol`s `true`, `false`, and
64
+ # `nil`) are never returned. In the example below, #each_object returns both the
65
+ # numbers we defined and several constants defined in the Math module.
66
+ #
67
+ # If no block is given, an enumerator is returned instead.
68
+ #
69
+ # a = 102.7
70
+ # b = 95 # Won't be returned
71
+ # c = 12345678987654321
72
+ # count = ObjectSpace.each_object(Numeric) {|x| p x }
73
+ # puts "Total count: #{count}"
74
+ #
75
+ # *produces:*
76
+ #
77
+ # 12345678987654321
78
+ # 102.7
79
+ # 2.71828182845905
80
+ # 3.14159265358979
81
+ # 2.22044604925031e-16
82
+ # 1.7976931348623157e+308
83
+ # 2.2250738585072e-308
84
+ # Total count: 7
85
+ #
86
+ def self.each_object: (?Module `module`) -> Enumerator[untyped, Integer]
87
+ | (?Module `module`) { (untyped obj) -> void } -> Integer
88
+
89
+ def self.garbage_collect: (?full_mark: bool, ?immediate_mark: bool, ?immediate_sweep: bool) -> void
90
+
91
+ # Removes all finalizers for *obj*.
92
+ #
93
+ def self.undefine_finalizer: [X] (X obj) -> X
94
+
95
+ private
96
+
97
+ def garbage_collect: (?full_mark: bool, ?immediate_mark: bool, ?immediate_sweep: bool) -> void
98
+ end
@@ -118,7 +118,7 @@ module RBS
118
118
  next if files.include?(path)
119
119
 
120
120
  files << path
121
- buffer = Buffer.new(name: path.to_s, content: path.read)
121
+ buffer = Buffer.new(name: path.to_s, content: path.read(encoding: "UTF-8"))
122
122
 
123
123
  Parser.parse_signature(buffer).each do |decl|
124
124
  yield decl, buffer, source, path
@@ -1,5 +1,9 @@
1
1
  module RBS
2
2
  class EnvironmentWalker
3
+ InstanceNode = Struct.new(:type_name, keyword_init: true)
4
+ SingletonNode = Struct.new(:type_name, keyword_init: true)
5
+ TypeNameNode = Struct.new(:type_name, keyword_init: true)
6
+
3
7
  attr_reader :env
4
8
 
5
9
  def initialize(env:)
@@ -23,50 +27,70 @@ module RBS
23
27
  include TSort
24
28
 
25
29
  def tsort_each_node(&block)
26
- env.class_decls.each_key(&block)
27
- env.interface_decls.each_key(&block)
28
- env.alias_decls.each_key(&block)
30
+ env.class_decls.each_key do |type_name|
31
+ yield InstanceNode.new(type_name: type_name)
32
+ yield SingletonNode.new(type_name: type_name)
33
+ end
34
+ env.interface_decls.each_key do |type_name|
35
+ yield TypeNameNode.new(type_name: type_name)
36
+ end
37
+ env.alias_decls.each_key do |type_name|
38
+ yield TypeNameNode.new(type_name: type_name)
39
+ end
29
40
  end
30
41
 
31
- def tsort_each_child(name, &block)
42
+ def tsort_each_child(node, &block)
43
+ name = node.type_name
44
+
32
45
  unless name.namespace.empty?
33
- yield name.namespace.to_type_name
46
+ yield SingletonNode.new(type_name: name.namespace.to_type_name)
34
47
  end
35
48
 
36
- case
37
- when name.class?, name.interface?
38
- definitions = []
39
-
49
+ case node
50
+ when TypeNameNode
40
51
  case
41
- when name.class?
42
- definitions << builder.build_instance(name)
43
- definitions << builder.build_singleton(name)
44
52
  when name.interface?
45
- definitions << builder.build_interface(name)
53
+ definition = builder.build_interface(name)
54
+ unless only_ancestors?
55
+ definition.each_type do |type|
56
+ each_type_name type, &block
57
+ end
58
+ end
59
+ when name.alias?
60
+ each_type_name builder.expand_alias(name), &block
61
+ else
62
+ raise "Unexpected TypeNameNode with type_name=#{name}"
46
63
  end
47
64
 
48
- definitions.each do |definition|
49
- if ancestors = definition.ancestors
50
- ancestors.ancestors.each do |ancestor|
51
- yield ancestor.name
65
+ when InstanceNode, SingletonNode
66
+ definition = if node.is_a?(InstanceNode)
67
+ builder.build_instance(name)
68
+ else
69
+ builder.build_singleton(name)
70
+ end
71
+
72
+ if ancestors = definition.ancestors
73
+ ancestors.ancestors.each do |ancestor|
74
+ case ancestor
75
+ when Definition::Ancestor::Instance
76
+ yield InstanceNode.new(type_name: ancestor.name)
52
77
 
53
- case ancestor
54
- when Definition::Ancestor::Instance
78
+ unless only_ancestors?
55
79
  ancestor.args.each do |type|
56
80
  each_type_name type, &block
57
81
  end
58
82
  end
83
+ when Definition::Ancestor::Singleton
84
+ yield SingletonNode.new(type_name: ancestor.name)
59
85
  end
60
86
  end
87
+ end
61
88
 
62
- unless only_ancestors?
63
- definition.each_type do |type|
64
- each_type_name type, &block
65
- end
89
+ unless only_ancestors?
90
+ definition.each_type do |type|
91
+ each_type_name type, &block
66
92
  end
67
93
  end
68
- when name.alias?
69
- each_type_name builder.expand_alias(name), &block
70
94
  end
71
95
  end
72
96
 
@@ -83,14 +107,19 @@ module RBS
83
107
  when RBS::Types::Bases::Nil
84
108
  when RBS::Types::Variable
85
109
  when RBS::Types::ClassSingleton
86
- yield type.name
87
- when RBS::Types::ClassInstance, RBS::Types::Interface
88
- yield type.name
110
+ yield SingletonNode.new(type_name: type.name)
111
+ when RBS::Types::ClassInstance
112
+ yield InstanceNode.new(type_name: type.name)
113
+ type.args.each do |ty|
114
+ each_type_name(ty, &block)
115
+ end
116
+ when RBS::Types::Interface
117
+ yield TypeNameNode.new(type_name: type.name)
89
118
  type.args.each do |ty|
90
119
  each_type_name(ty, &block)
91
120
  end
92
121
  when RBS::Types::Alias
93
- yield type.name
122
+ yield TypeNameNode.new(type_name: type.name)
94
123
  when RBS::Types::Union, RBS::Types::Intersection, RBS::Types::Tuple
95
124
  type.types.each do |ty|
96
125
  each_type_name ty, &block
@@ -1,6 +1,22 @@
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
+ end
19
+
4
20
  attr_reader :source_decls
5
21
  attr_reader :toplevel_members
6
22
 
@@ -52,10 +68,10 @@ module RBS
52
68
  end
53
69
  end
54
70
 
55
- process RubyVM::AbstractSyntaxTree.parse(string), decls: source_decls, comments: comments, singleton: false
71
+ process RubyVM::AbstractSyntaxTree.parse(string), decls: source_decls, comments: comments, context: Context.initial
56
72
  end
57
73
 
58
- def process(node, decls:, comments:, singleton:)
74
+ def process(node, decls:, comments:, context:)
59
75
  case node.type
60
76
  when :CLASS
61
77
  class_name, super_class, *class_body = node.children
@@ -71,9 +87,11 @@ module RBS
71
87
 
72
88
  decls.push kls
73
89
 
90
+ new_ctx = Context.initial(namespace: context.namespace + kls.name.to_namespace)
74
91
  each_node class_body do |child|
75
- process child, decls: kls.members, comments: comments, singleton: false
92
+ process child, decls: kls.members, comments: comments, context: new_ctx
76
93
  end
94
+ remove_unnecessary_accessibility_methods! kls.members
77
95
 
78
96
  when :MODULE
79
97
  module_name, *module_body = node.children
@@ -90,9 +108,11 @@ module RBS
90
108
 
91
109
  decls.push mod
92
110
 
111
+ new_ctx = Context.initial(namespace: context.namespace + mod.name.to_namespace)
93
112
  each_node module_body do |child|
94
- process child, decls: mod.members, comments: comments, singleton: false
113
+ process child, decls: mod.members, comments: comments, context: new_ctx
95
114
  end
115
+ remove_unnecessary_accessibility_methods! mod.members
96
116
 
97
117
  when :SCLASS
98
118
  this, body = node.children
@@ -101,14 +121,13 @@ module RBS
101
121
  RBS.logger.warn "`class <<` syntax with not-self may be compiled to incorrect code: #{this}"
102
122
  end
103
123
 
104
- each_child(body) do |child|
105
- process child, decls: decls, comments: comments, singleton: true
106
- end
124
+ ctx = Context.initial.tap { |ctx| ctx.singleton = true }
125
+ process_children(body, decls: decls, comments: comments, context: ctx)
107
126
 
108
127
  when :DEFN, :DEFS
109
128
  if node.type == :DEFN
110
129
  def_name, def_body = node.children
111
- kind = singleton ? :singleton : :instance
130
+ kind = context.method_kind
112
131
  else
113
132
  _, def_name, def_body = node.children
114
133
  kind = :singleton
@@ -140,14 +159,14 @@ module RBS
140
159
  member = AST::Members::Alias.new(
141
160
  new_name: new_name,
142
161
  old_name: old_name,
143
- kind: singleton ? :singleton : :instance,
162
+ kind: context.singleton ? :singleton : :instance,
144
163
  annotations: [],
145
164
  location: nil,
146
165
  comment: comments[node.first_lineno - 1],
147
166
  )
148
167
  decls.push member unless decls.include?(member)
149
168
 
150
- when :FCALL
169
+ when :FCALL, :VCALL
151
170
  # Inside method definition cannot reach here.
152
171
  args = node.children[1]&.children || []
153
172
 
@@ -166,7 +185,7 @@ module RBS
166
185
  end
167
186
  when :extend
168
187
  args.each do |arg|
169
- if (name = const_to_name(arg))
188
+ if (name = const_to_name(arg, context: context))
170
189
  decls << AST::Members::Extend.new(
171
190
  name: name,
172
191
  args: [],
@@ -220,16 +239,61 @@ module RBS
220
239
  decls << AST::Members::Alias.new(
221
240
  new_name: new_name,
222
241
  old_name: old_name,
223
- kind: singleton ? :singleton : :instance,
242
+ kind: context.singleton ? :singleton : :instance,
224
243
  annotations: [],
225
244
  location: nil,
226
245
  comment: comments[node.first_lineno - 1],
227
246
  )
228
247
  end
248
+ when :module_function
249
+ if args.empty?
250
+ context.module_function = true
251
+ else
252
+ module_func_context = context.dup.tap { |ctx| ctx.module_function = true }
253
+ args.each do |arg|
254
+ if arg && (name = literal_to_symbol(arg))
255
+ if i = find_def_index_by_name(decls, name)
256
+ decls[i] = decls[i].update(kind: :singleton_instance)
257
+ end
258
+ elsif arg
259
+ process arg, decls: decls, comments: comments, context: module_func_context
260
+ end
261
+ end
262
+ end
263
+ when :public, :private
264
+ accessibility = __send__(node.children[0])
265
+ if args.empty?
266
+ decls << accessibility
267
+ else
268
+ args.each do |arg|
269
+ if arg && (name = literal_to_symbol(arg))
270
+ if i = find_def_index_by_name(decls, name)
271
+ current = current_accessibility(decls, i)
272
+ if current != accessibility
273
+ decls.insert(i + 1, current)
274
+ decls.insert(i, accessibility)
275
+ end
276
+ end
277
+ end
278
+ end
279
+
280
+ # For `private def foo` syntax
281
+ current = current_accessibility(decls)
282
+ decls << accessibility
283
+ process_children(node, decls: decls, comments: comments, context: context)
284
+ decls << current
285
+ end
286
+ else
287
+ process_children(node, decls: decls, comments: comments, context: context)
229
288
  end
230
289
 
231
- each_child node do |child|
232
- process child, decls: decls, comments: comments, singleton: singleton
290
+ when :ITER
291
+ method_name = node.children.first.children.first
292
+ case method_name
293
+ when :refine
294
+ # ignore
295
+ else
296
+ process_children(node, decls: decls, comments: comments, context: context)
233
297
  end
234
298
 
235
299
  when :CDECL
@@ -248,13 +312,17 @@ module RBS
248
312
  )
249
313
 
250
314
  else
251
- each_child node do |child|
252
- process child, decls: decls, comments: comments, singleton: singleton
253
- end
315
+ process_children(node, decls: decls, comments: comments, context: context)
316
+ end
317
+ end
318
+
319
+ def process_children(node, decls:, comments:, context:)
320
+ each_child node do |child|
321
+ process child, decls: decls, comments: comments, context: context
254
322
  end
255
323
  end
256
324
 
257
- def const_to_name(node)
325
+ def const_to_name(node, context: nil)
258
326
  case node&.type
259
327
  when :CONST
260
328
  TypeName.new(name: node.children[0], namespace: Namespace.empty)
@@ -268,6 +336,8 @@ module RBS
268
336
  TypeName.new(name: node.children[1], namespace: namespace)
269
337
  when :COLON3
270
338
  TypeName.new(name: node.children[0], namespace: Namespace.root)
339
+ when :SELF
340
+ context&.then { |c| c.namespace.to_type_name }
271
341
  end
272
342
  end
273
343
 
@@ -586,6 +656,59 @@ module RBS
586
656
  def untyped
587
657
  @untyped ||= Types::Bases::Any.new(location: nil)
588
658
  end
659
+
660
+ def private
661
+ @private ||= AST::Members::Private.new(location: nil)
662
+ end
663
+
664
+ def public
665
+ @public ||= AST::Members::Public.new(location: nil)
666
+ end
667
+
668
+ def current_accessibility(decls, index = decls.size)
669
+ idx = decls.slice(0, index).rindex { |decl| decl == private || decl == public }
670
+ (idx && decls[idx]) || public
671
+ end
672
+
673
+ def remove_unnecessary_accessibility_methods!(decls)
674
+ current = public
675
+ idx = 0
676
+
677
+ loop do
678
+ decl = decls[idx] or break
679
+ if current == decl
680
+ decls.delete_at(idx)
681
+ next
682
+ end
683
+
684
+ if 0 < idx && is_accessibility?(decls[idx - 1]) && is_accessibility?(decl)
685
+ decls.delete_at(idx - 1)
686
+ idx -= 1
687
+ current = current_accessibility(decls, idx)
688
+ next
689
+ end
690
+
691
+ current = decl if is_accessibility?(decl)
692
+ idx += 1
693
+ end
694
+
695
+ decls.pop while decls.last && is_accessibility?(decls.last)
696
+ end
697
+
698
+ def is_accessibility?(decl)
699
+ decl == public || decl == private
700
+ end
701
+
702
+ def find_def_index_by_name(decls, name)
703
+ decls.find_index do |decl|
704
+ case decl
705
+ when AST::Members::MethodDefinition, AST::Members::AttrReader
706
+ decl.name == name
707
+ when AST::Members::AttrWriter
708
+ decl.name == :"#{name}="
709
+ end
710
+ end
711
+ end
589
712
  end
590
713
  end
591
714
  end
@@ -94,6 +94,7 @@ module RBS
94
94
  optional_positionals << Types::Function::Param.new(name: name, type: untyped)
95
95
  when :rest
96
96
  requireds = trailing_positionals
97
+ name = nil if name == :* # For `def f(...) end` syntax
97
98
  rest = Types::Function::Param.new(name: name, type: untyped)
98
99
  when :keyreq
99
100
  required_keywords[name] = Types::Function::Param.new(name: nil, type: untyped)
@@ -27,26 +27,28 @@ module RBS
27
27
  :>> => "rshift",
28
28
  :~ => "tilda"
29
29
  }
30
- def self.alias_names(target)
30
+ def self.alias_names(target, random)
31
+ suffix = "#{RBS::Test.suffix}_#{random}"
32
+
31
33
  case target
32
34
  when *OPERATORS.keys
33
35
  name = OPERATORS[target]
34
36
  [
35
- "#{name}____with__#{Test.suffix}",
36
- "#{name}____without__#{Test.suffix}"
37
+ "#{name}____with__#{suffix}",
38
+ "#{name}____without__#{suffix}"
37
39
  ]
38
40
  else
39
41
  aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1
40
42
 
41
43
  [
42
- "#{aliased_target}__with__#{Test.suffix}#{punctuation}",
43
- "#{aliased_target}__without__#{Test.suffix}#{punctuation}"
44
+ "#{aliased_target}__with__#{suffix}#{punctuation}",
45
+ "#{aliased_target}__without__#{suffix}#{punctuation}"
44
46
  ]
45
47
  end
46
48
  end
47
49
 
48
- def self.setup_alias_method_chain(klass, target)
49
- with_method, without_method = alias_names(target)
50
+ def self.setup_alias_method_chain(klass, target, random:)
51
+ with_method, without_method = alias_names(target, random)
50
52
 
51
53
  RBS.logger.debug "alias name: #{target}, #{with_method}, #{without_method}"
52
54
 
@@ -65,12 +67,12 @@ module RBS
65
67
  end
66
68
  end
67
69
 
68
- def self.hook_method_source(prefix, method_name, key)
69
- with_name, without_name = alias_names(method_name)
70
+ def self.hook_method_source(prefix, method_name, key, random:)
71
+ with_name, without_name = alias_names(method_name, random)
70
72
  full_method_name = "#{prefix}#{method_name}"
71
73
 
72
74
  [__LINE__ + 1, <<RUBY]
73
- def #{with_name}(*args)
75
+ def #{with_name}(*args, &block)
74
76
  ::RBS.logger.debug { "#{full_method_name} with arguments: [" + args.map(&:inspect).join(", ") + "]" }
75
77
 
76
78
  begin
@@ -78,11 +80,17 @@ def #{with_name}(*args)
78
80
  block_calls = []
79
81
 
80
82
  if block_given?
83
+ receiver = self
81
84
  result = __send__(:"#{without_name}", *args) do |*block_args|
82
85
  return_from_block = false
83
86
 
84
87
  begin
85
- block_result = yield(*block_args)
88
+ block_result = if receiver.equal?(self)
89
+ yield(*block_args)
90
+ else
91
+ instance_exec(*block_args, &block)
92
+ end
93
+
86
94
  return_from_block = true
87
95
  ensure
88
96
  exn = $!
@@ -154,17 +162,19 @@ RUBY
154
162
  end
155
163
 
156
164
  def self.hook_instance_method(klass, method, key:)
157
- line, source = hook_method_source("#{klass}#", method, key)
165
+ random = SecureRandom.hex(4)
166
+ line, source = hook_method_source("#{klass}#", method, key, random: random)
158
167
 
159
168
  klass.module_eval(source, __FILE__, line)
160
- setup_alias_method_chain klass, method
169
+ setup_alias_method_chain klass, method, random: random
161
170
  end
162
171
 
163
172
  def self.hook_singleton_method(klass, method, key:)
164
- line, source = hook_method_source("#{klass}.",method, key)
173
+ random = SecureRandom.hex(4)
174
+ line, source = hook_method_source("#{klass}.",method, key, random: random)
165
175
 
166
176
  klass.singleton_class.module_eval(source, __FILE__, line)
167
- setup_alias_method_chain klass.singleton_class, method
177
+ setup_alias_method_chain klass.singleton_class, method, random: random
168
178
  end
169
179
  end
170
180
  end
@@ -288,7 +288,12 @@ module RBS
288
288
  end
289
289
  when Types::ClassSingleton
290
290
  klass = get_class(type.name) or return false
291
- val == klass
291
+ singleton_class = begin
292
+ klass.singleton_class
293
+ rescue TypeError
294
+ return false
295
+ end
296
+ val.is_a?(singleton_class)
292
297
  when Types::Interface
293
298
  methods = Set.new(Test.call(val, METHODS))
294
299
  if (definition = builder.build_interface(type.name))
@@ -1,3 +1,3 @@
1
1
  module RBS
2
- VERSION = "0.17.0"
2
+ VERSION = "0.18.0"
3
3
  end
@@ -0,0 +1,111 @@
1
+ # The Singleton module implements the Singleton pattern.
2
+ #
3
+ # ## Usage
4
+ #
5
+ # To use Singleton, include the module in your class.
6
+ #
7
+ # class Klass
8
+ # include Singleton
9
+ # # ...
10
+ # end
11
+ #
12
+ # This ensures that only one instance of Klass can be created.
13
+ #
14
+ # a,b = Klass.instance, Klass.instance
15
+ #
16
+ # a == b
17
+ # # => true
18
+ #
19
+ # Klass.new
20
+ # # => NoMethodError - new is private ...
21
+ #
22
+ # The instance is created at upon the first call of Klass.instance().
23
+ #
24
+ # class OtherKlass
25
+ # include Singleton
26
+ # # ...
27
+ # end
28
+ #
29
+ # ObjectSpace.each_object(OtherKlass){}
30
+ # # => 0
31
+ #
32
+ # OtherKlass.instance
33
+ # ObjectSpace.each_object(OtherKlass){}
34
+ # # => 1
35
+ #
36
+ # This behavior is preserved under inheritance and cloning.
37
+ #
38
+ # ## Implementation
39
+ #
40
+ # This above is achieved by:
41
+ #
42
+ # * Making Klass.new and Klass.allocate private.
43
+ #
44
+ # * Overriding Klass.inherited(sub_klass) and Klass.clone() to ensure that the
45
+ # Singleton properties are kept when inherited and cloned.
46
+ #
47
+ # * Providing the Klass.instance() method that returns the same object each
48
+ # time it is called.
49
+ #
50
+ # * Overriding Klass._load(str) to call Klass.instance().
51
+ #
52
+ # * Overriding Klass#clone and Klass#dup to raise TypeErrors to prevent
53
+ # cloning or duping.
54
+ #
55
+ #
56
+ # ## Singleton and Marshal
57
+ #
58
+ # By default Singleton's #_dump(depth) returns the empty string. Marshalling by
59
+ # default will strip state information, e.g. instance variables from the
60
+ # instance. Classes using Singleton can provide custom _load(str) and
61
+ # _dump(depth) methods to retain some of the previous state of the instance.
62
+ #
63
+ # require 'singleton'
64
+ #
65
+ # class Example
66
+ # include Singleton
67
+ # attr_accessor :keep, :strip
68
+ # def _dump(depth)
69
+ # # this strips the @strip information from the instance
70
+ # Marshal.dump(@keep, depth)
71
+ # end
72
+ #
73
+ # def self._load(str)
74
+ # instance.keep = Marshal.load(str)
75
+ # instance
76
+ # end
77
+ # end
78
+ #
79
+ # a = Example.instance
80
+ # a.keep = "keep this"
81
+ # a.strip = "get rid of this"
82
+ #
83
+ # stored_state = Marshal.dump(a)
84
+ #
85
+ # a.keep = nil
86
+ # a.strip = nil
87
+ # b = Marshal.load(stored_state)
88
+ # p a == b # => true
89
+ # p a.keep # => "keep this"
90
+ # p a.strip # => nil
91
+ module Singleton
92
+ def self.__init__: (Class klass) -> Class
93
+
94
+ def self.instance: () -> instance
95
+
96
+ public
97
+
98
+ # By default, do not retain any state when marshalling.
99
+ #
100
+ def _dump: (?Integer depth) -> String
101
+
102
+ # Raises a TypeError to prevent cloning.
103
+ #
104
+ def clone: () -> bot
105
+
106
+ # Raises a TypeError to prevent duping.
107
+ #
108
+ def dup: () -> bot
109
+ end
110
+
111
+ Singleton::VERSION: String
@@ -0,0 +1,221 @@
1
+ # YAML Ain't Markup Language
2
+ #
3
+ # This module provides a Ruby interface for data serialization in YAML format.
4
+ #
5
+ # The YAML module is an alias of Psych, the YAML engine for Ruby.
6
+ #
7
+ # ## Usage
8
+ #
9
+ # Working with YAML can be very simple, for example:
10
+ #
11
+ # require 'yaml'
12
+ # # Parse a YAML string
13
+ # YAML.load("--- foo") #=> "foo"
14
+ #
15
+ # # Emit some YAML
16
+ # YAML.dump("foo") # => "--- foo\n...\n"
17
+ # { :a => 'b'}.to_yaml # => "---\n:a: b\n"
18
+ #
19
+ # As the implementation is provided by the Psych library, detailed documentation
20
+ # can be found in that library's docs (also part of standard library).
21
+ #
22
+ # ## Security
23
+ #
24
+ # Do not use YAML to load untrusted data. Doing so is unsafe and could allow
25
+ # malicious input to execute arbitrary code inside your application. Please see
26
+ # doc/security.rdoc for more information.
27
+ #
28
+ # ## History
29
+ #
30
+ # Syck was the original for YAML implementation in Ruby's standard library
31
+ # developed by why the lucky stiff.
32
+ #
33
+ # You can still use Syck, if you prefer, for parsing and emitting YAML, but you
34
+ # must install the 'syck' gem now in order to use it.
35
+ #
36
+ # In older Ruby versions, ie. <= 1.9, Syck is still provided, however it was
37
+ # completely removed with the release of Ruby 2.0.0.
38
+ #
39
+ # ## More info
40
+ #
41
+ # For more advanced details on the implementation see Psych, and also check out
42
+ # http://yaml.org for spec details and other helpful information.
43
+ #
44
+ # Psych is maintained by Aaron Patterson on github:
45
+ # https://github.com/ruby/psych
46
+ #
47
+ # Syck can also be found on github: https://github.com/ruby/syck
48
+ #
49
+ module YAML
50
+ # YAML + DBM = YDBM
51
+ #
52
+ # YAML::DBM provides the same interface as ::DBM.
53
+ #
54
+ # However, while DBM only allows strings for both keys and values,
55
+ # this library allows one to use most Ruby objects for values
56
+ # by first converting them to YAML. Keys must be strings.
57
+ #
58
+ # Conversion to and from YAML is performed automatically.
59
+ #
60
+ # See the documentation for ::DBM and ::YAML for more information.
61
+ class DBM < ::DBM
62
+ VERSION: ::String
63
+
64
+ # :call-seq:
65
+ # ydbm[key] -> value
66
+ #
67
+ # Return value associated with +key+ from database.
68
+ #
69
+ # Returns +nil+ if there is no such +key+.
70
+ #
71
+ # See #fetch for more information.
72
+ def []: (String key) -> untyped
73
+
74
+ # :call-seq:
75
+ # ydbm[key] = value
76
+ #
77
+ # Set +key+ to +value+ in database.
78
+ #
79
+ # +value+ will be converted to YAML before storage.
80
+ #
81
+ # See #store for more information.
82
+ def []=: (String key, untyped val) -> untyped
83
+
84
+ # :call-seq:
85
+ # ydbm.fetch( key, ifnone = nil )
86
+ # ydbm.fetch( key ) { |key| ... }
87
+ #
88
+ # Return value associated with +key+.
89
+ #
90
+ # If there is no value for +key+ and no block is given, returns +ifnone+.
91
+ #
92
+ # Otherwise, calls block passing in the given +key+.
93
+ #
94
+ # See ::DBM#fetch for more information.
95
+ def fetch: (String keystr, ?untyped? ifnone) { (untyped) -> untyped } -> untyped
96
+
97
+ # Deprecated, used YAML::DBM#key instead.
98
+ # ----
99
+ # Note:
100
+ # YAML::DBM#index makes warning from internal of ::DBM#index.
101
+ # It says 'DBM#index is deprecated; use DBM#key', but DBM#key
102
+ # behaves not same as DBM#index.
103
+ #
104
+ def index: (String keystr) -> untyped
105
+
106
+ # :call-seq:
107
+ # ydbm.key(value) -> string
108
+ #
109
+ # Returns the key for the specified value.
110
+ def key: (String keystr) -> String
111
+
112
+ # :call-seq:
113
+ # ydbm.values_at(*keys)
114
+ #
115
+ # Returns an array containing the values associated with the given keys.
116
+ def values_at: (*untyped keys) -> Array[untyped]
117
+
118
+ # :call-seq:
119
+ # ydbm.delete(key)
120
+ #
121
+ # Deletes value from database associated with +key+.
122
+ #
123
+ # Returns value or +nil+.
124
+ def delete: (String key) -> untyped
125
+
126
+ def delete_if: () { (untyped, untyped) -> untyped } -> untyped
127
+
128
+ # :call-seq:
129
+ # ydbm.reject { |key, value| ... }
130
+ #
131
+ # Converts the contents of the database to an in-memory Hash, then calls
132
+ # Hash#reject with the specified code block, returning a new Hash.
133
+ def reject: () { (untyped, untyped) -> untyped } -> Hash[untyped, untyped]
134
+
135
+ def each_pair: () { (untyped, untyped) -> untyped } -> untyped
136
+
137
+ def each_value: () { (untyped) -> untyped } -> untyped
138
+
139
+ # :call-seq:
140
+ # ydbm.values
141
+ #
142
+ # Returns an array of values from the database.
143
+ def values: () -> untyped
144
+
145
+ # :call-seq:
146
+ # ydbm.has_value?(value)
147
+ #
148
+ # Returns true if specified +value+ is found in the database.
149
+ def has_value?: (untyped val) -> (::TrueClass | ::FalseClass)
150
+
151
+ # :call-seq:
152
+ # ydbm.invert -> hash
153
+ #
154
+ # Returns a Hash (not a DBM database) created by using each value in the
155
+ # database as a key, with the corresponding key as its value.
156
+ #
157
+ # Note that all values in the hash will be Strings, but the keys will be
158
+ # actual objects.
159
+ def invert: () -> Hash[untyped, untyped]
160
+
161
+ # :call-seq:
162
+ # ydbm.replace(hash) -> ydbm
163
+ #
164
+ # Replaces the contents of the database with the contents of the specified
165
+ # object. Takes any object which implements the each_pair method, including
166
+ # Hash and DBM objects.
167
+ def replace: (Hash[untyped, untyped] | DBM hsh) -> YAML::DBM
168
+
169
+ # :call-seq:
170
+ # ydbm.shift -> [key, value]
171
+ #
172
+ # Removes a [key, value] pair from the database, and returns it.
173
+ # If the database is empty, returns +nil+.
174
+ #
175
+ # The order in which values are removed/returned is not guaranteed.
176
+ def shift: () -> (Array[untyped] | untyped)
177
+
178
+ # :call-seq:
179
+ # ydbm.select { |key, value| ... }
180
+ # ydbm.select(*keys)
181
+ #
182
+ # If a block is provided, returns a new array containing [key, value] pairs
183
+ # for which the block returns true.
184
+ #
185
+ # Otherwise, same as #values_at
186
+ def select: (*untyped keys) { (untyped, untyped) -> untyped } -> Array[untyped]
187
+
188
+ # :call-seq:
189
+ # ydbm.store(key, value) -> value
190
+ #
191
+ # Stores +value+ in database with +key+ as the index. +value+ is converted
192
+ # to YAML before being stored.
193
+ #
194
+ # Returns +value+
195
+ def store: (String key, untyped val) -> untyped
196
+
197
+ # :call-seq:
198
+ # ydbm.update(hash) -> ydbm
199
+ #
200
+ # Updates the database with multiple values from the specified object.
201
+ # Takes any object which implements the each_pair method, including
202
+ # Hash and DBM objects.
203
+ #
204
+ # Returns +self+.
205
+ def update: (Hash[untyped, untyped]) -> YAML::DBM
206
+
207
+ # :call-seq:
208
+ # ydbm.to_a -> array
209
+ #
210
+ # Converts the contents of the database to an array of [key, value] arrays,
211
+ # and returns it.
212
+ def to_a: () -> Array [untyped]
213
+
214
+ # :call-seq:
215
+ # ydbm.to_hash -> hash
216
+ #
217
+ # Converts the contents of the database to an in-memory Hash object, and
218
+ # returns it.
219
+ def to_hash: () -> Hash[untyped, untyped]
220
+ end
221
+ end
@@ -0,0 +1,53 @@
1
+ # YAML::Store provides the same functionality as PStore, except it uses YAML to
2
+ # dump objects instead of Marshal.
3
+ #
4
+ # ## Example
5
+ #
6
+ # require 'yaml/store'
7
+ #
8
+ # Person = Struct.new :first_name, :last_name
9
+ #
10
+ # people = [Person.new("Bob", "Smith"), Person.new("Mary", "Johnson")]
11
+ #
12
+ # store = YAML::Store.new "test.store"
13
+ #
14
+ # store.transaction do
15
+ # store["people"] = people
16
+ # store["greeting"] = { "hello" => "world" }
17
+ # end
18
+ #
19
+ # After running the above code, the contents of "test.store" will be:
20
+ #
21
+ # ---
22
+ # people:
23
+ # - !ruby/struct:Person
24
+ # first_name: Bob
25
+ # last_name: Smith
26
+ # - !ruby/struct:Person
27
+ # first_name: Mary
28
+ # last_name: Johnson
29
+ # greeting:
30
+ # hello: world
31
+ #
32
+ class YAML::Store < ::PStore
33
+ # Creates a new YAML::Store object, which will store data in `file_name`. If the
34
+ # file does not already exist, it will be created.
35
+ #
36
+ # YAML::Store objects are always reentrant. But if *thread_safe* is set to true,
37
+ # then it will become thread-safe at the cost of a minor performance hit.
38
+ #
39
+ # Options passed in through `yaml_opts` will be used when converting the store
40
+ # to YAML via Hash#to_yaml().
41
+ #
42
+ def initialize: (*untyped o) -> YAML::Store
43
+
44
+ def dump: (untyped table) -> String
45
+
46
+ def empty_marshal_checksum: () -> String
47
+
48
+ def empty_marshal_data: () -> String
49
+
50
+ def load: (String) -> untyped
51
+
52
+ def marshal_dump_supports_canonical_option?: () -> ::FalseClass
53
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rbs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.17.0
4
+ version: 0.18.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Soutaro Matsumoto
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-11-14 00:00:00.000000000 Z
11
+ date: 2020-12-01 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: RBS is the language for type signatures for Ruby and standard library
14
14
  definitions.
@@ -74,6 +74,7 @@ files:
74
74
  - core/nil_class.rbs
75
75
  - core/numeric.rbs
76
76
  - core/object.rbs
77
+ - core/object_space.rbs
77
78
  - core/proc.rbs
78
79
  - core/process.rbs
79
80
  - core/random.rbs
@@ -213,6 +214,7 @@ files:
213
214
  - stdlib/pty/0/pty.rbs
214
215
  - stdlib/securerandom/0/securerandom.rbs
215
216
  - stdlib/set/0/set.rbs
217
+ - stdlib/singleton/0/singleton.rbs
216
218
  - stdlib/tmpdir/0/tmpdir.rbs
217
219
  - stdlib/tsort/0/cyclic.rbs
218
220
  - stdlib/tsort/0/interfaces.rbs
@@ -223,6 +225,8 @@ files:
223
225
  - stdlib/uri/0/https.rbs
224
226
  - stdlib/uri/0/ldap.rbs
225
227
  - stdlib/uri/0/ldaps.rbs
228
+ - stdlib/yaml/0/dbm.rbs
229
+ - stdlib/yaml/0/store.rbs
226
230
  - stdlib/zlib/0/zlib.rbs
227
231
  - steep/Gemfile
228
232
  - steep/Gemfile.lock
@@ -249,7 +253,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
249
253
  - !ruby/object:Gem::Version
250
254
  version: '0'
251
255
  requirements: []
252
- rubygems_version: 3.1.2
256
+ rubygems_version: 3.2.0.rc.2
253
257
  signing_key:
254
258
  specification_version: 4
255
259
  summary: Type signature for Ruby.