rbs 0.8.0 → 0.12.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 (77) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +32 -0
  3. data/Gemfile +1 -0
  4. data/README.md +1 -1
  5. data/Rakefile +9 -4
  6. data/Steepfile +28 -0
  7. data/bin/steep +4 -0
  8. data/bin/test_runner.rb +10 -5
  9. data/docs/syntax.md +14 -1
  10. data/lib/rbs/ast/comment.rb +12 -0
  11. data/lib/rbs/ast/declarations.rb +15 -9
  12. data/lib/rbs/ast/members.rb +3 -8
  13. data/lib/rbs/buffer.rb +1 -1
  14. data/lib/rbs/cli.rb +66 -2
  15. data/lib/rbs/definition.rb +35 -16
  16. data/lib/rbs/definition_builder.rb +111 -68
  17. data/lib/rbs/environment.rb +24 -11
  18. data/lib/rbs/environment_loader.rb +55 -35
  19. data/lib/rbs/location.rb +14 -3
  20. data/lib/rbs/method_type.rb +5 -5
  21. data/lib/rbs/namespace.rb +14 -3
  22. data/lib/rbs/parser.y +8 -20
  23. data/lib/rbs/prototype/rb.rb +3 -5
  24. data/lib/rbs/prototype/rbi.rb +1 -4
  25. data/lib/rbs/prototype/runtime.rb +0 -4
  26. data/lib/rbs/substitution.rb +4 -3
  27. data/lib/rbs/test/hook.rb +1 -0
  28. data/lib/rbs/test/setup.rb +17 -12
  29. data/lib/rbs/test/setup_helper.rb +15 -0
  30. data/lib/rbs/test/tester.rb +59 -13
  31. data/lib/rbs/test/type_check.rb +43 -14
  32. data/lib/rbs/type_name.rb +18 -1
  33. data/lib/rbs/type_name_resolver.rb +10 -3
  34. data/lib/rbs/types.rb +27 -21
  35. data/lib/rbs/validator.rb +4 -0
  36. data/lib/rbs/variance_calculator.rb +8 -5
  37. data/lib/rbs/version.rb +1 -1
  38. data/lib/rbs/writer.rb +7 -3
  39. data/sig/annotation.rbs +26 -0
  40. data/sig/buffer.rbs +28 -0
  41. data/sig/builtin_names.rbs +41 -0
  42. data/sig/comment.rbs +26 -0
  43. data/sig/declarations.rbs +202 -0
  44. data/sig/definition.rbs +129 -0
  45. data/sig/definition_builder.rbs +95 -0
  46. data/sig/environment.rbs +94 -0
  47. data/sig/environment_loader.rbs +4 -0
  48. data/sig/location.rbs +52 -0
  49. data/sig/members.rbs +160 -0
  50. data/sig/method_types.rbs +40 -0
  51. data/sig/namespace.rbs +124 -0
  52. data/sig/polyfill.rbs +3 -0
  53. data/sig/rbs.rbs +3 -0
  54. data/sig/substitution.rbs +39 -0
  55. data/sig/type_name_resolver.rbs +24 -0
  56. data/sig/typename.rbs +70 -0
  57. data/sig/types.rbs +361 -0
  58. data/sig/util.rbs +13 -0
  59. data/sig/variance_calculator.rbs +35 -0
  60. data/stdlib/bigdecimal/big_decimal.rbs +887 -0
  61. data/stdlib/bigdecimal/math/big_math.rbs +142 -0
  62. data/stdlib/builtin/array.rbs +2 -1
  63. data/stdlib/builtin/builtin.rbs +0 -3
  64. data/stdlib/builtin/hash.rbs +1 -1
  65. data/stdlib/builtin/math.rbs +26 -26
  66. data/stdlib/builtin/struct.rbs +9 -10
  67. data/stdlib/date/date.rbs +1056 -0
  68. data/stdlib/date/date_time.rbs +582 -0
  69. data/stdlib/forwardable/forwardable.rbs +204 -0
  70. data/stdlib/json/json.rbs +6 -0
  71. data/stdlib/set/set.rbs +1 -1
  72. data/stdlib/uri/file.rbs +167 -0
  73. data/stdlib/uri/generic.rbs +875 -0
  74. data/stdlib/zlib/zlib.rbs +392 -0
  75. data/steep/Gemfile +3 -0
  76. data/steep/Gemfile.lock +55 -0
  77. metadata +39 -6
@@ -75,29 +75,16 @@ module RBS
75
75
  self.class.gem_sig_path(name, version)
76
76
  end
77
77
 
78
- def each_signature(path = nil, immediate: true, &block)
78
+ def each_signature(path, immediate: true, &block)
79
79
  if block_given?
80
- if path
81
- case
82
- when path.file?
83
- if path.extname == ".rbs" || immediate
84
- yield path
85
- end
86
- when path.directory?
87
- path.children.each do |child|
88
- each_signature child, immediate: false, &block
89
- end
80
+ case
81
+ when path.file?
82
+ if path.extname == ".rbs" || immediate
83
+ yield path
90
84
  end
91
- else
92
- paths.each do |path|
93
- case path
94
- when Pathname
95
- each_signature path, immediate: immediate, &block
96
- when LibraryPath
97
- each_signature path.path, immediate: immediate, &block
98
- when GemPath
99
- each_signature path.path, immediate: immediate, &block
100
- end
85
+ when path.directory?
86
+ path.children.each do |child|
87
+ each_signature child, immediate: false, &block
101
88
  end
102
89
  end
103
90
  else
@@ -105,32 +92,65 @@ module RBS
105
92
  end
106
93
  end
107
94
 
108
- def no_builtin!
109
- @no_builtin = true
95
+ def each_library_path
96
+ paths.each do |path|
97
+ case path
98
+ when Pathname
99
+ yield path, path
100
+ when LibraryPath
101
+ yield path, path.path
102
+ when GemPath
103
+ yield path, path.path
104
+ end
105
+ end
106
+ end
107
+
108
+ def no_builtin!(skip = true)
109
+ @no_builtin = skip
110
+ self
110
111
  end
111
112
 
112
113
  def no_builtin?
113
114
  @no_builtin
114
115
  end
115
116
 
116
- def load(env:)
117
- signature_files = []
117
+ def each_decl
118
+ if block_given?
119
+ signature_files = []
118
120
 
119
- unless no_builtin?
120
- signature_files.push(*each_signature(stdlib_root + "builtin"))
121
- end
121
+ unless no_builtin?
122
+ each_signature(stdlib_root + "builtin") do |path|
123
+ signature_files << [:stdlib, path]
124
+ end
125
+ end
122
126
 
123
- each_signature do |path|
124
- signature_files.push path
127
+ each_library_path do |library_path, pathname|
128
+ each_signature(pathname) do |path|
129
+ signature_files << [library_path, path]
130
+ end
131
+ end
132
+
133
+ signature_files.each do |lib_path, file_path|
134
+ buffer = Buffer.new(name: file_path.to_s, content: file_path.read)
135
+ Parser.parse_signature(buffer).each do |decl|
136
+ yield decl, buffer, file_path, lib_path
137
+ end
138
+ end
139
+ else
140
+ enum_for :each_decl
125
141
  end
142
+ end
143
+
144
+ def load(env:)
145
+ loadeds = []
126
146
 
127
- signature_files.each do |file|
128
- buffer = Buffer.new(name: file.to_s, content: file.read)
147
+ each_decl do |decl, buffer, file_path, lib_path|
129
148
  env.buffers.push(buffer)
130
- Parser.parse_signature(buffer).each do |decl|
131
- env << decl
132
- end
149
+ env << decl
150
+ loadeds << [decl, file_path, lib_path]
133
151
  end
152
+
153
+ loadeds
134
154
  end
135
155
  end
136
156
  end
@@ -43,7 +43,7 @@ module RBS
43
43
  end
44
44
 
45
45
  def source
46
- @source ||= buffer.content[start_pos...end_pos]
46
+ @source ||= buffer.content[start_pos...end_pos] or raise
47
47
  end
48
48
 
49
49
  def to_s
@@ -73,8 +73,19 @@ module RBS
73
73
  end
74
74
  end
75
75
 
76
- def self.concat(*locations)
77
- locations.inject {|l1, l2| l1 + l2 }
76
+ def concat(*others)
77
+ others.each { |other| self << other }
78
+ self
79
+ end
80
+
81
+ def <<(other)
82
+ if other
83
+ raise "Invalid concat: buffer=#{buffer.name}, other.buffer=#{other.buffer.name}" unless other.buffer == buffer
84
+ @end_pos = other.end_pos
85
+ @source = nil
86
+ @end_loc = nil
87
+ end
88
+ self
78
89
  end
79
90
 
80
91
  def pred?(loc)
@@ -93,7 +93,7 @@ module RBS
93
93
  end
94
94
 
95
95
  def each_type(&block)
96
- if block_given?
96
+ if block
97
97
  type.each_type(&block)
98
98
  self.block&.yield_self do |b|
99
99
  b.type.each_type(&block)
@@ -105,10 +105,10 @@ module RBS
105
105
 
106
106
  def to_s
107
107
  s = case
108
- when block && block.required
109
- "(#{type.param_to_s}) { (#{block.type.param_to_s}) -> #{block.type.return_to_s} } -> #{type.return_to_s}"
110
- when block
111
- "(#{type.param_to_s}) ?{ (#{block.type.param_to_s}) -> #{block.type.return_to_s} } -> #{type.return_to_s}"
108
+ when (b = block) && b.required
109
+ "(#{type.param_to_s}) { (#{b.type.param_to_s}) -> #{b.type.return_to_s} } -> #{type.return_to_s}"
110
+ when b = block
111
+ "(#{type.param_to_s}) ?{ (#{b.type.param_to_s}) -> #{b.type.return_to_s} } -> #{type.return_to_s}"
112
112
  else
113
113
  "(#{type.param_to_s}) -> #{type.return_to_s}"
114
114
  end
@@ -63,7 +63,9 @@ module RBS
63
63
  end
64
64
 
65
65
  def split
66
- [parent, path.last]
66
+ last = path.last or return
67
+ parent = self.parent
68
+ [parent, last]
67
69
  end
68
70
 
69
71
  def to_s
@@ -77,6 +79,10 @@ module RBS
77
79
 
78
80
  def to_type_name
79
81
  parent, name = split
82
+
83
+ raise unless name
84
+ raise unless parent
85
+
80
86
  TypeName.new(name: name, namespace: parent)
81
87
  end
82
88
 
@@ -88,14 +94,13 @@ module RBS
88
94
  end
89
95
  end
90
96
 
91
-
92
97
  def ascend
93
98
  if block_given?
94
99
  current = self
95
100
 
96
101
  until current.empty?
97
102
  yield current
98
- current = current.parent
103
+ current = _ = current.parent
99
104
  end
100
105
 
101
106
  yield current
@@ -107,3 +112,9 @@ module RBS
107
112
  end
108
113
  end
109
114
  end
115
+
116
+ module Kernel
117
+ def Namespace(name)
118
+ RBS::Namespace.parse(name)
119
+ end
120
+ end
@@ -435,14 +435,6 @@ rule
435
435
  method_member:
436
436
  annotations attributes overload kDEF method_kind def_name method_types {
437
437
  location = val[3].location + val[6].last.location
438
- types = val[6].map do |type|
439
- case type
440
- when LocatedValue
441
- type.value
442
- else
443
- type
444
- end
445
- end
446
438
 
447
439
  last_type = val[6].last
448
440
  if last_type.is_a?(LocatedValue) && last_type.value == :dot3
@@ -458,16 +450,14 @@ rule
458
450
  types: val[6],
459
451
  annotations: val[0],
460
452
  location: location,
461
- comment: leading_comment(val[0].first&.location || val[1].first&.location || val[2]&.location || val[3].location),
462
- attributes: val[1].map(&:value),
453
+ comment: leading_comment(val[0].first&.location || val[2]&.location || val[3].location),
463
454
  overload: overload || !!val[2]
464
455
  )
465
456
  }
466
457
 
467
458
  attributes:
468
- { result = [] }
469
459
  | attributes kINCOMPATIBLE {
470
- result = val[0].push(val[1])
460
+ RBS.logger.warn "`incompatible` method attribute is deprecated and ignored."
471
461
  }
472
462
 
473
463
  method_kind:
@@ -1164,15 +1154,13 @@ def leading_comment(location)
1164
1154
  end
1165
1155
 
1166
1156
  def push_comment(string, location)
1167
- new_comment = AST::Comment.new(string: string+"\n", location: location)
1168
-
1169
- if (prev_comment = leading_comment(location)) && prev_comment.location.start_column == location.start_column
1170
- @comments.delete prev_comment.location.end_line
1171
- new_comment = AST::Comment.new(string: prev_comment.string + new_comment.string,
1172
- location: prev_comment.location + new_comment.location)
1157
+ if (comment = leading_comment(location)) && comment.location.start_column == location.start_column
1158
+ comment.concat(string: "#{string}\n", location: location)
1159
+ @comments[comment.location.end_line] = comment
1160
+ else
1161
+ new_comment = AST::Comment.new(string: "#{string}\n", location: location)
1162
+ @comments[new_comment.location.end_line] = new_comment
1173
1163
  end
1174
-
1175
- @comments[new_comment.location.end_line] = new_comment
1176
1164
  end
1177
1165
 
1178
1166
  def new_token(type, value = input.matched)
@@ -36,7 +36,7 @@ module RBS
36
36
  tokens.each.with_object({}) do |token, hash|
37
37
  if token[1] == :on_comment
38
38
  line = token[0][0]
39
- body = token[2][2..]
39
+ body = token[2][2..-1]
40
40
 
41
41
  body = "\n" if body.empty?
42
42
 
@@ -130,7 +130,6 @@ module RBS
130
130
  types: types,
131
131
  kind: kind,
132
132
  comment: comments[node.first_lineno - 1],
133
- attributes: [],
134
133
  overload: false
135
134
  )
136
135
 
@@ -354,7 +353,6 @@ module RBS
354
353
  Types::Bases::Nil.new(location: nil)
355
354
  when :LIT
356
355
  lit = node.children[0]
357
- name = lit.class.name
358
356
  case lit
359
357
  when Symbol
360
358
  if lit.match?(/\A[ -~]+\z/)
@@ -365,7 +363,7 @@ module RBS
365
363
  when Integer
366
364
  Types::Literal.new(literal: lit, location: nil)
367
365
  else
368
- type_name = TypeName.new(name: name, namespace: Namespace.root)
366
+ type_name = TypeName.new(name: lit.class.name.to_sym, namespace: Namespace.root)
369
367
  Types::ClassInstance.new(name: type_name, args: [], location: nil)
370
368
  end
371
369
  when :ZLIST, :ZARRAY
@@ -421,7 +419,7 @@ module RBS
421
419
 
422
420
  types = types.map do |t|
423
421
  if t.is_a?(Types::Literal)
424
- type_name = TypeName.new(name: t.literal.class.name, namespace: Namespace.root)
422
+ type_name = TypeName.new(name: t.literal.class.name.to_sym, namespace: Namespace.root)
425
423
  Types::ClassInstance.new(name: type_name, args: [], location: nil)
426
424
  else
427
425
  t
@@ -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)
@@ -7,6 +7,7 @@ module RBS
7
7
  OPERATORS = {
8
8
  :== => "eqeq",
9
9
  :=== => "eqeqeq",
10
+ :!= => "noteq",
10
11
  :+ => "plus",
11
12
  :- => "minus",
12
13
  :* => "star",
@@ -9,21 +9,26 @@ logger = Logger.new(STDERR)
9
9
 
10
10
  begin
11
11
  opts = Shellwords.shellsplit(ENV["RBS_TEST_OPT"] || "-I sig")
12
- filter = ENV.fetch('RBS_TEST_TARGET').split(',').map! { |e| e.strip }
12
+ filter = ENV.fetch('RBS_TEST_TARGET', "").split(',').map! { |e| e.strip }
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
19
- rescue Exception => e
20
- raise e.message
21
+ end
22
+
23
+ if filter.empty?
21
24
  STDERR.puts "rbs/test/setup handles the following environment variables:"
22
25
  STDERR.puts " [REQUIRED] RBS_TEST_TARGET: test target class name, `Foo::Bar,Foo::Baz` for each class or `Foo::*` for all classes under `Foo`"
23
26
  STDERR.puts " [OPTIONAL] RBS_TEST_SKIP: skip testing classes"
24
27
  STDERR.puts " [OPTIONAL] RBS_TEST_OPT: options for signatures (`-r` for libraries or `-I` for signatures)"
25
28
  STDERR.puts " [OPTIONAL] RBS_TEST_LOGLEVEL: one of debug|info|warn|error|fatal (defaults to info)"
26
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"
27
32
  exit 1
28
33
  end
29
34
 
@@ -50,16 +55,16 @@ end
50
55
 
51
56
  tester = RBS::Test::Tester.new(env: env)
52
57
 
58
+ module_name = Module.instance_method(:name)
59
+
53
60
  TracePoint.trace :end do |tp|
54
- class_name = tp.self.name&.yield_self {|name| to_absolute_typename name }
61
+ class_name = module_name.bind(tp.self).call&.yield_self {|name| to_absolute_typename name }
55
62
 
56
63
  if class_name
57
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) }
58
- if tester.checkers.none? {|hook| hook.klass == tp.self }
59
- if env.class_decls.key?(class_name)
60
- logger.info "Setting up hooks for #{class_name}"
61
- tester.install!(tp.self, sample_size: sample_size)
62
- end
65
+ if env.class_decls.key?(class_name)
66
+ logger.info "Setting up hooks for #{class_name}"
67
+ tester.install!(tp.self, sample_size: sample_size, unchecked_classes: unchecked_classes)
63
68
  end
64
69
  end
65
70
  end
@@ -67,8 +72,8 @@ end
67
72
 
68
73
  at_exit do
69
74
  if $!.nil? || $!.is_a?(SystemExit) && $!.success?
70
- logger.warn "No type checker was installed! " if tester.checkers.empty?
75
+ if tester.targets.empty?
76
+ logger.debug { "No type checker was installed!" }
77
+ end
71
78
  end
72
79
  end
73
-
74
-