rbs 0.17.0 → 0.20.1

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.
@@ -387,19 +387,19 @@ module RBS
387
387
  if block
388
388
  if (type = vars[block])
389
389
  if type.is_a?(Types::Proc)
390
- method_block = MethodType::Block.new(required: true, type: type.type)
390
+ method_block = Types::Block.new(required: true, type: type.type)
391
391
  elsif type.is_a?(Types::Bases::Any)
392
- method_block = MethodType::Block.new(
392
+ method_block = Types::Block.new(
393
393
  required: true,
394
394
  type: Types::Function.empty(Types::Bases::Any.new(location: nil))
395
395
  )
396
396
  # Handle an optional block like `T.nilable(T.proc.void)`.
397
397
  elsif type.is_a?(Types::Optional) && type.type.is_a?(Types::Proc)
398
- method_block = MethodType::Block.new(required: false, type: type.type.type)
398
+ method_block = Types::Block.new(required: false, type: type.type.type)
399
399
  else
400
400
  STDERR.puts "Unexpected block type: #{type}"
401
401
  PP.pp args_node, STDERR
402
- method_block = MethodType::Block.new(
402
+ method_block = Types::Block.new(
403
403
  required: true,
404
404
  type: Types::Function.empty(Types::Bases::Any.new(location: nil))
405
405
  )
@@ -485,7 +485,7 @@ module RBS
485
485
  Types::Tuple.new(types: types, location: nil)
486
486
  else
487
487
  if proc_type?(type_node)
488
- Types::Proc.new(type: method_type(nil, type_node, variables: variables).type, location: nil)
488
+ Types::Proc.new(type: method_type(nil, type_node, variables: variables).type, block: nil, location: nil)
489
489
  else
490
490
  STDERR.puts "Unexpected type_node:"
491
491
  PP.pp type_node, STDERR
@@ -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)
@@ -102,7 +103,7 @@ module RBS
102
103
  when :keyrest
103
104
  rest_keywords = Types::Function::Param.new(name: nil, type: untyped)
104
105
  when :block
105
- block = MethodType::Block.new(
106
+ block = Types::Block.new(
106
107
  type: Types::Function.empty(untyped).update(rest_positionals: Types::Function::Param.new(name: nil, type: untyped)),
107
108
  required: true
108
109
  )
@@ -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,18 @@ def #{with_name}(*args)
78
80
  block_calls = []
79
81
 
80
82
  if block_given?
81
- result = __send__(:"#{without_name}", *args) do |*block_args|
83
+ receiver = self
84
+
85
+ wrapped_block = proc do |*block_args|
82
86
  return_from_block = false
83
87
 
84
88
  begin
85
- block_result = yield(*block_args)
89
+ block_result = if receiver.equal?(self)
90
+ yield(*block_args)
91
+ else
92
+ instance_exec(*block_args, &block)
93
+ end
94
+
86
95
  return_from_block = true
87
96
  ensure
88
97
  exn = $!
@@ -109,7 +118,9 @@ def #{with_name}(*args)
109
118
  end
110
119
 
111
120
  block_result
112
- end
121
+ end.ruby2_keywords
122
+
123
+ result = __send__(:"#{without_name}", *args, &wrapped_block)
113
124
  else
114
125
  result = __send__(:"#{without_name}", *args)
115
126
  end
@@ -154,17 +165,19 @@ RUBY
154
165
  end
155
166
 
156
167
  def self.hook_instance_method(klass, method, key:)
157
- line, source = hook_method_source("#{klass}#", method, key)
168
+ random = SecureRandom.hex(4)
169
+ line, source = hook_method_source("#{klass}#", method, key, random: random)
158
170
 
159
171
  klass.module_eval(source, __FILE__, line)
160
- setup_alias_method_chain klass, method
172
+ setup_alias_method_chain klass, method, random: random
161
173
  end
162
174
 
163
175
  def self.hook_singleton_method(klass, method, key:)
164
- line, source = hook_method_source("#{klass}.",method, key)
176
+ random = SecureRandom.hex(4)
177
+ line, source = hook_method_source("#{klass}.",method, key, random: random)
165
178
 
166
179
  klass.singleton_class.module_eval(source, __FILE__, line)
167
- setup_alias_method_chain klass.singleton_class, method
180
+ setup_alias_method_chain klass.singleton_class, method, random: random
168
181
  end
169
182
  end
170
183
  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))
@@ -947,44 +947,100 @@ module RBS
947
947
  end
948
948
  end
949
949
 
950
+ class Block
951
+ attr_reader :type
952
+ attr_reader :required
953
+
954
+ def initialize(type:, required:)
955
+ @type = type
956
+ @required = required
957
+ end
958
+
959
+ def ==(other)
960
+ other.is_a?(Block) &&
961
+ other.type == type &&
962
+ other.required == required
963
+ end
964
+
965
+ def to_json(*a)
966
+ {
967
+ type: type,
968
+ required: required
969
+ }.to_json(*a)
970
+ end
971
+
972
+ def sub(s)
973
+ self.class.new(
974
+ type: type.sub(s),
975
+ required: required
976
+ )
977
+ end
978
+
979
+ def map_type(&block)
980
+ Block.new(
981
+ required: required,
982
+ type: type.map_type(&block)
983
+ )
984
+ end
985
+ end
986
+
950
987
  class Proc
951
988
  attr_reader :type
989
+ attr_reader :block
952
990
  attr_reader :location
953
991
 
954
- def initialize(location:, type:)
992
+ def initialize(location:, type:, block:)
955
993
  @type = type
994
+ @block = block
956
995
  @location = location
957
996
  end
958
997
 
959
998
  def ==(other)
960
- other.is_a?(Proc) && other.type == type
999
+ other.is_a?(Proc) && other.type == type && other.block == block
961
1000
  end
962
1001
 
963
1002
  alias eql? ==
964
1003
 
965
1004
  def hash
966
- self.class.hash ^ type.hash
1005
+ self.class.hash ^ type.hash ^ block.hash
967
1006
  end
968
1007
 
969
1008
  def free_variables(set = Set[])
970
1009
  type.free_variables(set)
1010
+ block&.type&.free_variables(set)
1011
+ set
971
1012
  end
972
1013
 
973
1014
  def to_json(*a)
974
- { class: :proc, type: type, location: location }.to_json(*a)
1015
+ {
1016
+ class: :proc,
1017
+ type: type,
1018
+ block: block,
1019
+ location: location
1020
+ }.to_json(*a)
975
1021
  end
976
1022
 
977
1023
  def sub(s)
978
- self.class.new(type: type.sub(s), location: location)
1024
+ self.class.new(type: type.sub(s), block: block&.sub(s), location: location)
979
1025
  end
980
1026
 
981
1027
  def to_s(level = 0)
982
- "^(#{type.param_to_s}) -> #{type.return_to_s}".lstrip
1028
+ case
1029
+ when b = block
1030
+ if b.required
1031
+ "^(#{type.param_to_s}) { (#{b.type.param_to_s}) -> #{b.type.return_to_s} } -> #{type.return_to_s}"
1032
+ else
1033
+ "^(#{type.param_to_s}) ?{ (#{b.type.param_to_s}) -> #{b.type.return_to_s} } -> #{type.return_to_s}"
1034
+ end
1035
+ else
1036
+ "^(#{type.param_to_s}) -> #{type.return_to_s}"
1037
+ end
983
1038
  end
984
1039
 
985
1040
  def each_type(&block)
986
1041
  if block
987
1042
  type.each_type(&block)
1043
+ self.block&.type&.each_type(&block)
988
1044
  else
989
1045
  enum_for :each_type
990
1046
  end
@@ -993,6 +1049,7 @@ module RBS
993
1049
  def map_type_name(&block)
994
1050
  Proc.new(
995
1051
  type: type.map_type_name(&block),
1052
+ block: self.block&.map_type {|type| type.map_type_name(&block) },
996
1053
  location: location
997
1054
  )
998
1055
  end
@@ -1,3 +1,3 @@
1
1
  module RBS
2
- VERSION = "0.17.0"
2
+ VERSION = "0.20.1"
3
3
  end
@@ -285,7 +285,15 @@ module RBS
285
285
  else
286
286
  "(#{attr.ivar_name})"
287
287
  end
288
- "attr_#{kind} #{attr.name}#{var}: #{attr.type}"
288
+
289
+ receiver = case attr.kind
290
+ when :singleton
291
+ "self."
292
+ when :instance
293
+ ""
294
+ end
295
+
296
+ "attr_#{kind} #{receiver}#{attr.name}#{var}: #{attr.type}"
289
297
  end
290
298
 
291
299
  def preserve_empty_line(prev, decl)
@@ -165,6 +165,10 @@
165
165
  "name": {
166
166
  "type": "string"
167
167
  },
168
+ "kind": {
169
+ "type": "string",
170
+ "enum": ["instance", "singleton"]
171
+ },
168
172
  "type": {
169
173
  "$ref": "types.json"
170
174
  },
@@ -194,7 +198,7 @@
194
198
  "$ref": "location.json"
195
199
  }
196
200
  },
197
- "required": ["member", "name", "ivar_name", "type", "annotations", "comment", "location"]
201
+ "required": ["member", "name", "ivar_name", "type", "annotations", "kind", "comment", "location"]
198
202
  },
199
203
  "visibility": {
200
204
  "title": "Visibility specifier",
@@ -93,5 +93,8 @@ module RBS
93
93
  def validate_parameter_variance: (decl: AST::Declarations::Class | AST::Declarations::Module | AST::Declarations::Interface, methods: Hash[Symbol, Definition::Method]) -> void
94
94
 
95
95
  def expand_alias: (TypeName) -> Types::t
96
+
97
+ type attributes = AST::Members::AttrReader | AST::Members::AttrWriter | AST::Members::AttrAccessor
98
+ def build_attribute: (type_name: TypeName, definition: Definition, member: attributes, accessibility: Definition::accessibility) -> void
96
99
  end
97
100
  end
@@ -91,14 +91,17 @@ module RBS
91
91
  end
92
92
 
93
93
  module Attribute
94
+ type kind = :instance | :singleton
95
+
94
96
  attr_reader name: Symbol
95
97
  attr_reader type: Types::t
98
+ attr_reader kind: kind
96
99
  attr_reader ivar_name: Symbol | false | nil
97
100
  attr_reader annotations: Array[Annotation]
98
101
  attr_reader location: Location?
99
102
  attr_reader comment: Comment?
100
103
 
101
- def initialize: (name: Symbol, type: Types::t, ivar_name: Symbol | false | nil, annotations: Array[Annotation], location: Location?, comment: Comment?) -> void
104
+ def initialize: (name: Symbol, type: Types::t, ivar_name: Symbol | false | nil, kind: kind, annotations: Array[Annotation], location: Location?, comment: Comment?) -> void
102
105
 
103
106
  include _HashEqual
104
107
  end
@@ -1,24 +1,11 @@
1
1
  module RBS
2
2
  class MethodType
3
- class Block
4
- attr_reader type: Types::Function
5
- attr_reader required: bool
6
-
7
- def initialize: (type: Types::Function, required: boolish) -> void
8
-
9
- def ==: (untyped other) -> bool
10
-
11
- def to_json: (*untyped) -> String
12
-
13
- def sub: (Substitution) -> Block
14
- end
15
-
16
3
  attr_reader type_params: Array[Symbol]
17
4
  attr_reader type: Types::Function
18
- attr_reader block: Block?
5
+ attr_reader block: Types::Block?
19
6
  attr_reader location: Location?
20
7
 
21
- def initialize: (type_params: Array[Symbol], type: Types::Function, block: Block?, location: Location?) -> void
8
+ def initialize: (type_params: Array[Symbol], type: Types::Function, block: Types::Block?, location: Location?) -> void
22
9
 
23
10
  def ==: (untyped other) -> bool
24
11
 
@@ -26,7 +13,7 @@ module RBS
26
13
 
27
14
  def sub: (Substitution) -> MethodType
28
15
 
29
- def update: (?type_params: Array[Symbol], ?type: Types::Function, ?block: Block?, ?location: Location?) -> MethodType
16
+ def update: (?type_params: Array[Symbol], ?type: Types::Function, ?block: Types::Block?, ?location: Location?) -> MethodType
30
17
 
31
18
  def free_variables: (?Set[Symbol] set) -> Set[Symbol]
32
19
 
@@ -334,11 +334,27 @@ module RBS
334
334
  def has_keyword?: () -> bool
335
335
  end
336
336
 
337
+ class Block
338
+ attr_reader type: Types::Function
339
+ attr_reader required: boolish
340
+
341
+ def initialize: (type: Types::Function, required: boolish) -> void
342
+
343
+ def ==: (untyped other) -> bool
344
+
345
+ def to_json: (*untyped) -> String
346
+
347
+ def sub: (Substitution) -> Block
348
+
349
+ def map_type: () { (Types::t) -> Types::t } -> Block
350
+ end
351
+
337
352
  class Proc
338
353
  attr_reader type: Function
354
+ attr_reader block: Block?
339
355
  attr_reader location: Location?
340
356
 
341
- def initialize: (location: Location?, type: Function) -> void
357
+ def initialize: (location: Location?, type: Function, block: Block?) -> void
342
358
 
343
359
  include _TypeBase
344
360
  end
@@ -138,8 +138,6 @@ class DBM
138
138
  #
139
139
  def include?: (String) -> bool
140
140
 
141
- def index: (untyped) -> (String | NilClass)
142
-
143
141
  # Returns a Hash (not a DBM database) created by using each value in the
144
142
  # database as a key, with the corresponding key as its value.
145
143
  #
@@ -0,0 +1,119 @@
1
+ # Use the Monitor class when you want to have a lock object for blocks with
2
+ # mutual exclusion.
3
+ #
4
+ # require 'monitor'
5
+ #
6
+ # lock = Monitor.new
7
+ # lock.synchronize do
8
+ # # exclusive access
9
+ # end
10
+ class Monitor
11
+ public
12
+
13
+ def enter: () -> nil
14
+
15
+ def exit: () -> nil
16
+
17
+ def mon_check_owner: () -> nil
18
+
19
+ alias mon_enter enter
20
+
21
+ alias mon_exit exit
22
+
23
+ def mon_locked?: () -> bool
24
+
25
+ def mon_owned?: () -> bool
26
+
27
+ alias mon_synchronize synchronize
28
+
29
+ alias mon_try_enter try_enter
30
+
31
+ def new_cond: () -> ::MonitorMixin::ConditionVariable
32
+
33
+ def synchronize: [T] () { () -> T } -> T
34
+
35
+ def try_enter: () -> bool
36
+
37
+ # for compatibility
38
+ alias try_mon_enter try_enter
39
+
40
+ def wait_for_cond: (::MonitorMixin::ConditionVariable, Numeric? timeout) -> untyped
41
+ end
42
+
43
+ module MonitorMixin
44
+ def self.extend_object: (untyped obj) -> untyped
45
+
46
+ public
47
+
48
+ # Enters exclusive section.
49
+ def mon_enter: () -> nil
50
+
51
+ # Leaves exclusive section.
52
+ def mon_exit: () -> nil
53
+
54
+ # Returns true if this monitor is locked by any thread
55
+ def mon_locked?: () -> bool
56
+
57
+ # Returns true if this monitor is locked by current thread.
58
+ def mon_owned?: () -> bool
59
+
60
+ # Enters exclusive section and executes the block. Leaves the exclusive section
61
+ # automatically when the block exits. See example under `MonitorMixin`.
62
+ def mon_synchronize: [T] () { () -> T } -> T
63
+
64
+ # Attempts to enter exclusive section. Returns `false` if lock fails.
65
+ def mon_try_enter: () -> bool
66
+
67
+ # Creates a new MonitorMixin::ConditionVariable associated with the Monitor
68
+ # object.
69
+ def new_cond: () -> ::MonitorMixin::ConditionVariable
70
+
71
+ alias synchronize mon_synchronize
72
+
73
+ # For backward compatibility
74
+ alias try_mon_enter mon_try_enter
75
+
76
+ private
77
+
78
+ # Use `extend MonitorMixin` or `include MonitorMixin` instead of this
79
+ # constructor. Have look at the examples above to understand how to use this
80
+ # module.
81
+ def initialize: (*untyped) { (*untyped) -> untyped } -> void
82
+
83
+ def mon_check_owner: () -> nil
84
+
85
+ # Initializes the MonitorMixin after being included in a class or when an object
86
+ # has been extended with the MonitorMixin
87
+ def mon_initialize: () -> untyped
88
+ end
89
+
90
+ # FIXME: This isn't documented in Nutshell.
91
+ #
92
+ # Since MonitorMixin.new_cond returns a ConditionVariable, and the example above
93
+ # calls while_wait and signal, this class should be documented.
94
+ class MonitorMixin::ConditionVariable
95
+ public
96
+
97
+ # Wakes up all threads waiting for this lock.
98
+ def broadcast: () -> Thread::ConditionVariable
99
+
100
+ # Wakes up the first thread in line waiting for this lock.
101
+ def signal: () -> Thread::ConditionVariable
102
+
103
+ # Releases the lock held in the associated monitor and waits; reacquires the
104
+ # lock on wakeup.
105
+ #
106
+ # If `timeout` is given, this method returns after `timeout` seconds passed,
107
+ # even if no other thread doesn't signal.
108
+ def wait: (?Numeric? timeout) -> untyped
109
+
110
+ # Calls wait repeatedly until the given block yields a truthy value.
111
+ def wait_until: () { () -> boolish } -> untyped
112
+
113
+ # Calls wait repeatedly while the given block yields a truthy value.
114
+ def wait_while: () { () -> boolish } -> untyped
115
+
116
+ private
117
+
118
+ def initialize: (Monitor monitor) -> void
119
+ end