rbs 0.10.0 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +9 -9
  3. data/CHANGELOG.md +29 -0
  4. data/Gemfile +1 -0
  5. data/README.md +1 -1
  6. data/Rakefile +16 -6
  7. data/Steepfile +28 -0
  8. data/bin/steep +4 -0
  9. data/bin/test_runner.rb +7 -5
  10. data/docs/syntax.md +14 -1
  11. data/lib/rbs/ast/comment.rb +7 -1
  12. data/lib/rbs/ast/declarations.rb +15 -9
  13. data/lib/rbs/ast/members.rb +3 -8
  14. data/lib/rbs/buffer.rb +1 -1
  15. data/lib/rbs/cli.rb +72 -3
  16. data/lib/rbs/constant.rb +1 -1
  17. data/lib/rbs/constant_table.rb +9 -8
  18. data/lib/rbs/definition.rb +31 -14
  19. data/lib/rbs/definition_builder.rb +97 -67
  20. data/lib/rbs/environment.rb +28 -11
  21. data/lib/rbs/environment_loader.rb +67 -47
  22. data/lib/rbs/location.rb +1 -5
  23. data/lib/rbs/method_type.rb +5 -5
  24. data/lib/rbs/namespace.rb +14 -3
  25. data/lib/rbs/parser.y +2 -12
  26. data/lib/rbs/prototype/rb.rb +3 -5
  27. data/lib/rbs/prototype/rbi.rb +1 -4
  28. data/lib/rbs/prototype/runtime.rb +0 -4
  29. data/lib/rbs/substitution.rb +4 -3
  30. data/lib/rbs/test/setup.rb +5 -1
  31. data/lib/rbs/test/setup_helper.rb +15 -0
  32. data/lib/rbs/test/tester.rb +7 -5
  33. data/lib/rbs/test/type_check.rb +14 -2
  34. data/lib/rbs/type_name.rb +18 -1
  35. data/lib/rbs/type_name_resolver.rb +10 -3
  36. data/lib/rbs/types.rb +27 -21
  37. data/lib/rbs/variance_calculator.rb +9 -6
  38. data/lib/rbs/version.rb +1 -1
  39. data/lib/rbs/writer.rb +26 -17
  40. data/sig/annotation.rbs +26 -0
  41. data/sig/buffer.rbs +28 -0
  42. data/sig/builtin_names.rbs +41 -0
  43. data/sig/comment.rbs +26 -0
  44. data/sig/constant.rbs +21 -0
  45. data/sig/constant_table.rbs +30 -0
  46. data/sig/declarations.rbs +202 -0
  47. data/sig/definition.rbs +129 -0
  48. data/sig/definition_builder.rbs +94 -0
  49. data/sig/environment.rbs +94 -0
  50. data/sig/environment_loader.rbs +58 -0
  51. data/sig/location.rbs +52 -0
  52. data/sig/members.rbs +160 -0
  53. data/sig/method_types.rbs +40 -0
  54. data/sig/namespace.rbs +124 -0
  55. data/sig/polyfill.rbs +3 -0
  56. data/sig/rbs.rbs +3 -0
  57. data/sig/substitution.rbs +39 -0
  58. data/sig/type_name_resolver.rbs +24 -0
  59. data/sig/typename.rbs +70 -0
  60. data/sig/types.rbs +361 -0
  61. data/sig/util.rbs +13 -0
  62. data/sig/variance_calculator.rbs +35 -0
  63. data/sig/version.rbs +3 -0
  64. data/sig/writer.rbs +40 -0
  65. data/stdlib/bigdecimal/big_decimal.rbs +887 -0
  66. data/stdlib/bigdecimal/math/big_math.rbs +142 -0
  67. data/stdlib/builtin/array.rbs +2 -1
  68. data/stdlib/builtin/builtin.rbs +0 -3
  69. data/stdlib/builtin/hash.rbs +1 -1
  70. data/stdlib/builtin/kernel.rbs +2 -0
  71. data/stdlib/builtin/math.rbs +26 -26
  72. data/stdlib/builtin/struct.rbs +9 -10
  73. data/stdlib/date/date.rbs +1056 -0
  74. data/stdlib/date/date_time.rbs +582 -0
  75. data/stdlib/forwardable/forwardable.rbs +204 -0
  76. data/stdlib/pathname/pathname.rbs +2 -0
  77. data/stdlib/pty/pty.rbs +5 -29
  78. data/stdlib/set/set.rbs +1 -1
  79. data/stdlib/uri/file.rbs +167 -0
  80. data/stdlib/uri/generic.rbs +875 -0
  81. data/stdlib/uri/http.rbs +158 -0
  82. data/stdlib/uri/https.rbs +108 -0
  83. data/stdlib/uri/ldap.rbs +224 -0
  84. data/stdlib/uri/ldaps.rbs +108 -0
  85. data/stdlib/zlib/zlib.rbs +1 -1
  86. data/steep/Gemfile +3 -0
  87. data/steep/Gemfile.lock +51 -0
  88. metadata +45 -5
@@ -16,7 +16,7 @@ module RBS
16
16
  tokens.each.with_object({}) do |token, hash|
17
17
  if token[1] == :on_comment
18
18
  line = token[0][0]
19
- body = token[2][2..]
19
+ body = token[2][2..-1]
20
20
 
21
21
  body = "\n" if body.empty?
22
22
 
@@ -173,7 +173,6 @@ module RBS
173
173
  types: types,
174
174
  kind: :singleton,
175
175
  comment: comment,
176
- attributes: [],
177
176
  overload: false
178
177
  )
179
178
  end
@@ -194,7 +193,6 @@ module RBS
194
193
  types: types,
195
194
  kind: :instance,
196
195
  comment: comment,
197
- attributes: [],
198
196
  overload: false
199
197
  )
200
198
  end
@@ -502,7 +500,6 @@ module RBS
502
500
  else
503
501
  type_node.type == :CALL && proc_type?(type_node.children[0])
504
502
  end
505
-
506
503
  end
507
504
 
508
505
  def call_node?(node, name:, receiver: -> (node) { node.type == :CONST && node.children[0] == :T }, args: -> (node) { true })
@@ -154,7 +154,6 @@ module RBS
154
154
  location: nil,
155
155
  comment: method.comments[0],
156
156
  annotations: method.annotations,
157
- attributes: method.attributes,
158
157
  overload: false
159
158
  )
160
159
  return
@@ -193,7 +192,6 @@ module RBS
193
192
  location: nil,
194
193
  comment: nil,
195
194
  annotations: [],
196
- attributes: [],
197
195
  overload: false
198
196
  )
199
197
  end
@@ -227,7 +225,6 @@ module RBS
227
225
  location: nil,
228
226
  comment: nil,
229
227
  annotations: [],
230
- attributes: [],
231
228
  overload: false
232
229
  )
233
230
  end
@@ -262,7 +259,6 @@ module RBS
262
259
  location: nil,
263
260
  comment: nil,
264
261
  annotations: [],
265
- attributes: [],
266
262
  overload: false
267
263
  )
268
264
  end
@@ -31,10 +31,11 @@ module RBS
31
31
  def apply(ty)
32
32
  case ty
33
33
  when Types::Variable
34
+ # @type var ty: Types::Variable
34
35
  mapping[ty.name] || ty
35
36
  when Types::Bases::Instance
36
- if instance_type
37
- instance_type
37
+ if t = instance_type
38
+ t
38
39
  else
39
40
  ty
40
41
  end
@@ -44,7 +45,7 @@ module RBS
44
45
  end
45
46
 
46
47
  def without(*vars)
47
- self.class.new.tap do |subst|
48
+ Substitution.new.tap do |subst|
48
49
  subst.mapping.merge!(mapping)
49
50
  vars.each do |var|
50
51
  subst.mapping.delete(var)
@@ -13,6 +13,8 @@ begin
13
13
  skips = (ENV['RBS_TEST_SKIP'] || '').split(',').map! { |e| e.strip }
14
14
  RBS.logger_level = (ENV["RBS_TEST_LOGLEVEL"] || "info")
15
15
  sample_size = get_sample_size(ENV['RBS_TEST_SAMPLE_SIZE'] || '')
16
+ double_class = to_double_class(ENV['RBS_TEST_DOUBLE_SUITE'])
17
+ unchecked_classes = (ENV['RBS_TEST_UNCHECKED_CLASSES'] || '').split(',').map! { |unchecked_class| unchecked_class.strip }.push(*double_class)
16
18
  rescue InvalidSampleSizeError => exception
17
19
  RBS.logger.error exception.message
18
20
  exit 1
@@ -25,6 +27,8 @@ if filter.empty?
25
27
  STDERR.puts " [OPTIONAL] RBS_TEST_OPT: options for signatures (`-r` for libraries or `-I` for signatures)"
26
28
  STDERR.puts " [OPTIONAL] RBS_TEST_LOGLEVEL: one of debug|info|warn|error|fatal (defaults to info)"
27
29
  STDERR.puts " [OPTIONAL] RBS_TEST_SAMPLE_SIZE: sets the amount of values in a collection to be type-checked (Set to `ALL` to type check all the values)"
30
+ STDERR.puts " [OPTIONAL] RBS_TEST_DOUBLE_SUITE: sets the double suite in use (currently supported: minitest | rspec)"
31
+ STDERR.puts " [OPTIONAL] RBS_TEST_UNCHECKED_CLASSES: sets the classes that would not be checked"
28
32
  exit 1
29
33
  end
30
34
 
@@ -60,7 +64,7 @@ TracePoint.trace :end do |tp|
60
64
  if filter.any? {|f| match(to_absolute_typename(f).to_s, class_name.to_s) } && skips.none? {|f| match(f, class_name.to_s) }
61
65
  if env.class_decls.key?(class_name)
62
66
  logger.info "Setting up hooks for #{class_name}"
63
- tester.install!(tp.self, sample_size: sample_size)
67
+ tester.install!(tp.self, sample_size: sample_size, unchecked_classes: unchecked_classes)
64
68
  end
65
69
  end
66
70
  end
@@ -24,6 +24,21 @@ module RBS
24
24
  int_size
25
25
  end
26
26
  end
27
+
28
+ def to_double_class(double_suite)
29
+ return nil unless double_suite
30
+
31
+ case double_suite.downcase.strip
32
+ when 'rspec'
33
+ ['::RSpec::Mocks::Double']
34
+ when 'minitest'
35
+ ['::Minitest::Mock']
36
+ else
37
+ RBS.logger.warn "Unknown test suite - defaults to nil"
38
+ nil
39
+ end
40
+ end
41
+
27
42
  end
28
43
  end
29
44
  end
@@ -37,7 +37,7 @@ module RBS
37
37
  end
38
38
  end
39
39
 
40
- def install!(klass, sample_size:)
40
+ def install!(klass, sample_size:, unchecked_classes:)
41
41
  RBS.logger.info { "Installing runtime type checker in #{klass}..." }
42
42
 
43
43
  type_name = factory.type_name(klass.name).absolute!
@@ -45,7 +45,7 @@ module RBS
45
45
  builder.build_instance(type_name).tap do |definition|
46
46
  instance_key = new_key(type_name, "InstanceChecker")
47
47
  tester, set = instance_testers[klass] ||= [
48
- MethodCallTester.new(klass, builder, definition, kind: :instance, sample_size: sample_size),
48
+ MethodCallTester.new(klass, builder, definition, kind: :instance, sample_size: sample_size, unchecked_classes: unchecked_classes),
49
49
  Set[]
50
50
  ]
51
51
  Observer.register(instance_key, tester)
@@ -68,7 +68,7 @@ module RBS
68
68
  builder.build_singleton(type_name).tap do |definition|
69
69
  singleton_key = new_key(type_name, "SingletonChecker")
70
70
  tester, set = singleton_testers[klass] ||= [
71
- MethodCallTester.new(klass.singleton_class, builder, definition, kind: :singleton, sample_size: sample_size),
71
+ MethodCallTester.new(klass.singleton_class, builder, definition, kind: :singleton, sample_size: sample_size, unchecked_classes: unchecked_classes),
72
72
  Set[]
73
73
  ]
74
74
  Observer.register(singleton_key, tester)
@@ -111,13 +111,15 @@ module RBS
111
111
  attr_reader :builder
112
112
  attr_reader :kind
113
113
  attr_reader :sample_size
114
+ attr_reader :unchecked_classes
114
115
 
115
- def initialize(self_class, builder, definition, kind:, sample_size:)
116
+ def initialize(self_class, builder, definition, kind:, sample_size:, unchecked_classes:)
116
117
  @self_class = self_class
117
118
  @definition = definition
118
119
  @builder = builder
119
120
  @kind = kind
120
121
  @sample_size = sample_size
122
+ @unchecked_classes = unchecked_classes
121
123
  end
122
124
 
123
125
  def env
@@ -125,7 +127,7 @@ module RBS
125
127
  end
126
128
 
127
129
  def check
128
- @check ||= TypeCheck.new(self_class: self_class, builder: builder, sample_size: sample_size)
130
+ @check ||= TypeCheck.new(self_class: self_class, builder: builder, sample_size: sample_size, unchecked_classes: unchecked_classes)
129
131
  end
130
132
 
131
133
  def format_method_name(name)
@@ -4,15 +4,17 @@ module RBS
4
4
  attr_reader :self_class
5
5
  attr_reader :builder
6
6
  attr_reader :sample_size
7
+ attr_reader :unchecked_classes
7
8
 
8
9
  attr_reader :const_cache
9
10
 
10
11
  DEFAULT_SAMPLE_SIZE = 100
11
12
 
12
- def initialize(self_class:, builder:, sample_size:)
13
+ def initialize(self_class:, builder:, sample_size:, unchecked_classes:)
13
14
  @self_class = self_class
14
15
  @builder = builder
15
16
  @sample_size = sample_size
17
+ @unchecked_classes = unchecked_classes.uniq
16
18
  @const_cache = {}
17
19
  end
18
20
 
@@ -203,7 +205,16 @@ module RBS
203
205
  const_cache[type_name] ||= Object.const_get(type_name.to_s)
204
206
  end
205
207
 
208
+ def is_double?(value)
209
+ unchecked_classes.any? { |unchecked_class| Test.call(value, IS_AP, Object.const_get(unchecked_class))}
210
+ end
211
+
206
212
  def value(val, type)
213
+ if is_double?(val)
214
+ RBS.logger.info("A double (#{val.inspect}) is detected!")
215
+ return true
216
+ end
217
+
207
218
  case type
208
219
  when Types::Bases::Any
209
220
  true
@@ -295,7 +306,8 @@ module RBS
295
306
  Test.call(val, IS_AP, ::Array) &&
296
307
  type.types.map.with_index {|ty, index| value(val[index], ty) }.all?
297
308
  when Types::Record
298
- Test::call(val, IS_AP, ::Hash)
309
+ Test::call(val, IS_AP, ::Hash) &&
310
+ type.fields.map {|key, type| value(val[key], type) }.all?
299
311
  when Types::Proc
300
312
  Test::call(val, IS_AP, ::Proc)
301
313
  else
@@ -1,3 +1,4 @@
1
+
1
2
  module RBS
2
3
  class TypeName
3
4
  attr_reader :namespace
@@ -14,13 +15,15 @@ module RBS
14
15
  :alias
15
16
  when "_"
16
17
  :interface
18
+ else
19
+ raise
17
20
  end
18
21
  end
19
22
 
20
23
  def ==(other)
21
24
  other.is_a?(self.class) && other.namespace == namespace && other.name == name
22
25
  end
23
-
26
+
24
27
  alias eql? ==
25
28
 
26
29
  def hash
@@ -68,3 +71,17 @@ module RBS
68
71
  end
69
72
  end
70
73
  end
74
+
75
+ module Kernel
76
+ def TypeName(string)
77
+ absolute = string.start_with?("::")
78
+
79
+ *path, name = string.delete_prefix("::").split("::").map(&:to_sym)
80
+ raise unless name
81
+
82
+ RBS::TypeName.new(
83
+ name: name,
84
+ namespace: RBS::Namespace.new(path: path, absolute: absolute)
85
+ )
86
+ end
87
+ end
@@ -1,6 +1,6 @@
1
1
  module RBS
2
2
  class TypeNameResolver
3
- Query = Struct.new(:type_name, :context, keyword_init: true)
3
+ Query = _ = Struct.new(:type_name, :context, keyword_init: true)
4
4
 
5
5
  attr_reader :all_names
6
6
  attr_reader :cache
@@ -36,15 +36,22 @@ module RBS
36
36
  query = Query.new(type_name: type_name, context: context)
37
37
  try_cache(query) do
38
38
  path_head, *path_tail = type_name.to_namespace.path
39
+ raise unless path_head
40
+
39
41
  name_head = TypeName.new(name: path_head, namespace: Namespace.empty)
40
42
 
41
- absolute_head = context.each.find do |namespace|
43
+ absolute_head = context.find do |namespace|
44
+ # @type break: TypeName
42
45
  full_name = name_head.with_prefix(namespace)
43
46
  has_name?(full_name) and break full_name
44
47
  end
45
48
 
46
- if absolute_head
49
+ case absolute_head
50
+ when TypeName
47
51
  has_name?(Namespace.new(path: absolute_head.to_namespace.path.push(*path_tail), absolute: true).to_type_name)
52
+ when Namespace
53
+ # This cannot happen because the `context.find` doesn't return a Namespace.
54
+ raise
48
55
  end
49
56
  end
50
57
  end
@@ -1,3 +1,4 @@
1
+
1
2
  module RBS
2
3
  module Types
3
4
  module NoFreeVariables
@@ -77,7 +78,7 @@ module RBS
77
78
  when Types::Bases::Class
78
79
  'class'
79
80
  else
80
- raise "Unexpected base type: #{type.inspect}"
81
+ raise "Unexpected base type: #{inspect}"
81
82
  end
82
83
  end
83
84
  end
@@ -138,8 +139,6 @@ module RBS
138
139
  new(name: v, location: nil)
139
140
  when Array
140
141
  v.map {|x| new(name: x, location: nil) }
141
- else
142
- raise
143
142
  end
144
143
  end
145
144
 
@@ -227,7 +226,7 @@ module RBS
227
226
  end
228
227
 
229
228
  def each_type(&block)
230
- if block_given?
229
+ if block
231
230
  args.each(&block)
232
231
  else
233
232
  enum_for :each_type
@@ -380,7 +379,7 @@ module RBS
380
379
  end
381
380
 
382
381
  def each_type(&block)
383
- if block_given?
382
+ if block
384
383
  types.each(&block)
385
384
  else
386
385
  enum_for :each_type
@@ -445,7 +444,7 @@ module RBS
445
444
  end
446
445
 
447
446
  def each_type(&block)
448
- if block_given?
447
+ if block
449
448
  fields.each_value(&block)
450
449
  else
451
450
  enum_for :each_type
@@ -492,11 +491,15 @@ module RBS
492
491
  end
493
492
 
494
493
  def to_s(level = 0)
495
- if type.is_a?(RBS::Types::Literal) && type.literal.is_a?(Symbol)
496
- "#{type.to_s(1)} ?"
497
- else
498
- "#{type.to_s(1)}?"
494
+ case t = type
495
+ when RBS::Types::Literal
496
+ case t.literal
497
+ when Symbol
498
+ return "#{type.to_s(1)} ?"
499
+ end
499
500
  end
501
+
502
+ "#{type.to_s(1)}?"
500
503
  end
501
504
 
502
505
  def each_type
@@ -560,7 +563,7 @@ module RBS
560
563
  end
561
564
 
562
565
  def each_type(&block)
563
- if block_given?
566
+ if block
564
567
  types.each(&block)
565
568
  else
566
569
  enum_for :each_type
@@ -568,7 +571,7 @@ module RBS
568
571
  end
569
572
 
570
573
  def map_type(&block)
571
- if block_given?
574
+ if block
572
575
  Union.new(types: types.map(&block), location: location)
573
576
  else
574
577
  enum_for :map_type
@@ -629,7 +632,7 @@ module RBS
629
632
  end
630
633
 
631
634
  def each_type(&block)
632
- if block_given?
635
+ if block
633
636
  types.each(&block)
634
637
  else
635
638
  enum_for :each_type
@@ -637,7 +640,7 @@ module RBS
637
640
  end
638
641
 
639
642
  def map_type(&block)
640
- if block_given?
643
+ if block
641
644
  Intersection.new(types: types.map(&block), location: location)
642
645
  else
643
646
  enum_for :map_type
@@ -672,8 +675,8 @@ module RBS
672
675
  self.class.hash ^ type.hash ^ name.hash
673
676
  end
674
677
 
675
- def map_type
676
- if block_given?
678
+ def map_type(&block)
679
+ if block
677
680
  Param.new(name: name, type: yield(type))
678
681
  else
679
682
  enum_for :map_type
@@ -772,7 +775,7 @@ module RBS
772
775
  end
773
776
 
774
777
  def map_type(&block)
775
- if block_given?
778
+ if block
776
779
  Function.new(
777
780
  required_positionals: required_positionals.map {|param| param.map_type(&block) },
778
781
  optional_positionals: optional_positionals.map {|param| param.map_type(&block) },
@@ -810,7 +813,7 @@ module RBS
810
813
  end
811
814
 
812
815
  def each_param(&block)
813
- if block_given?
816
+ if block
814
817
  required_positionals.each(&block)
815
818
  optional_positionals.each(&block)
816
819
  rest_positionals&.yield_self(&block)
@@ -891,7 +894,9 @@ module RBS
891
894
  end
892
895
 
893
896
  def param_to_s
897
+ # @type var params: Array[String]
894
898
  params = []
899
+
895
900
  params.push(*required_positionals.map(&:to_s))
896
901
  params.push(*optional_positionals.map {|p| "?#{p}"})
897
902
  params.push("*#{rest_positionals}") if rest_positionals
@@ -927,8 +932,9 @@ module RBS
927
932
  def drop_tail
928
933
  case
929
934
  when !trailing_positionals.empty?
935
+ last = trailing_positionals.last or raise
930
936
  [
931
- trailing_positionals.last,
937
+ last,
932
938
  update(trailing_positionals: trailing_positionals.take(trailing_positionals.size - 1))
933
939
  ]
934
940
  else
@@ -960,7 +966,7 @@ module RBS
960
966
  self.class.hash ^ type.hash
961
967
  end
962
968
 
963
- def free_variables(set)
969
+ def free_variables(set = Set[])
964
970
  type.free_variables(set)
965
971
  end
966
972
 
@@ -977,7 +983,7 @@ module RBS
977
983
  end
978
984
 
979
985
  def each_type(&block)
980
- if block_given?
986
+ if block
981
987
  type.each_type(&block)
982
988
  else
983
989
  enum_for :each_type