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
@@ -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.16.0"
2
+ VERSION = "0.20.0"
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",
@@ -21,13 +21,13 @@ module RBS
21
21
  attr_reader defined_in: TypeName
22
22
  attr_reader implemented_in: TypeName?
23
23
 
24
- def initialize: (type: MethodType, member: method_member, defined_in: TypeName?, implemented_in: TypeName?) -> void
24
+ def initialize: (type: MethodType, member: method_member, defined_in: TypeName, implemented_in: TypeName?) -> void
25
25
 
26
26
  def comment: () -> AST::Comment?
27
27
 
28
28
  def annotations: () -> Array[AST::Annotation]
29
29
 
30
- def update: (?type: MethodType, ?member: method_member, ?defined_in: TypeName?, ?implemented_in: TypeName?) -> TypeDef
30
+ def update: (?type: MethodType, ?member: method_member, ?defined_in: TypeName, ?implemented_in: TypeName?) -> TypeDef
31
31
 
32
32
  def overload?: () -> bool
33
33
  end
@@ -42,8 +42,13 @@ module RBS
42
42
  attr_reader comments: Array[AST::Comment]
43
43
  attr_reader annotations: Array[AST::Annotation]
44
44
  attr_reader members: Array[method_member]
45
+ attr_reader alias_of: Method?
45
46
 
46
- def initialize: (super_method: Method?, defs: Array[TypeDef], accessibility: accessibility, ?annotations: Array[AST::Annotation]) -> void
47
+ def initialize: (super_method: Method?,
48
+ defs: Array[TypeDef],
49
+ accessibility: accessibility,
50
+ alias_of: Method?,
51
+ ?annotations: Array[AST::Annotation]) -> void
47
52
 
48
53
  def public?: () -> bool
49
54
 
@@ -62,7 +62,7 @@ module RBS
62
62
  def ensure_namespace!: (Namespace, location: Location?) -> void
63
63
 
64
64
  def build_singleton: (TypeName) -> Definition
65
-
65
+
66
66
  def build_instance: (TypeName) -> Definition
67
67
 
68
68
  def build_interface: (TypeName) -> Definition
@@ -71,11 +71,12 @@ module RBS
71
71
 
72
72
  def build_one_singleton: (TypeName) -> Definition
73
73
 
74
+ type ancestors = Definition::InstanceAncestors | Definition::SingletonAncestors | nil
74
75
  def merge_definitions: (TypeName,
75
76
  Array[[Definition::Ancestor::t, Definition]],
76
77
  entry: Environment::ModuleEntry | Environment::ClassEntry,
77
78
  self_type: Definition::self_type,
78
- ancestors: Array[Definition::Ancestor::t]) -> Definition
79
+ ancestors: ancestors) -> Definition
79
80
 
80
81
  type method_kind = :instance | :singleton
81
82
  def merge_method: (TypeName, Hash[Symbol, Definition::Method], Symbol, Definition::Method, Substitution, kind: method_kind) -> void
@@ -92,5 +93,8 @@ module RBS
92
93
  def validate_parameter_variance: (decl: AST::Declarations::Class | AST::Declarations::Module | AST::Declarations::Interface, methods: Hash[Symbol, Definition::Method]) -> void
93
94
 
94
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
95
99
  end
96
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