rbs 0.17.0 → 0.18.0

Sign up to get free protection for your applications and to get access to all the features.
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.