steep 0.1.0.pre2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +1 -1
  3. data/README.md +146 -33
  4. data/bin/smoke_runner.rb +43 -10
  5. data/lib/steep/ast/annotation/collection.rb +93 -0
  6. data/lib/steep/ast/annotation.rb +131 -0
  7. data/lib/steep/ast/buffer.rb +47 -0
  8. data/lib/steep/ast/location.rb +82 -0
  9. data/lib/steep/ast/method_type.rb +116 -0
  10. data/lib/steep/ast/signature/class.rb +33 -0
  11. data/lib/steep/ast/signature/const.rb +17 -0
  12. data/lib/steep/ast/signature/env.rb +123 -0
  13. data/lib/steep/ast/signature/extension.rb +21 -0
  14. data/lib/steep/ast/signature/gvar.rb +17 -0
  15. data/lib/steep/ast/signature/interface.rb +31 -0
  16. data/lib/steep/ast/signature/members.rb +71 -0
  17. data/lib/steep/ast/signature/module.rb +21 -0
  18. data/lib/steep/ast/type_params.rb +13 -0
  19. data/lib/steep/ast/types/any.rb +39 -0
  20. data/lib/steep/ast/types/bot.rb +39 -0
  21. data/lib/steep/ast/types/class.rb +35 -0
  22. data/lib/steep/ast/types/helper.rb +21 -0
  23. data/lib/steep/ast/types/instance.rb +39 -0
  24. data/lib/steep/ast/types/intersection.rb +74 -0
  25. data/lib/steep/ast/types/name.rb +124 -0
  26. data/lib/steep/ast/types/self.rb +39 -0
  27. data/lib/steep/ast/types/top.rb +39 -0
  28. data/lib/steep/ast/types/union.rb +74 -0
  29. data/lib/steep/ast/types/var.rb +57 -0
  30. data/lib/steep/ast/types/void.rb +35 -0
  31. data/lib/steep/cli.rb +28 -1
  32. data/lib/steep/drivers/annotations.rb +32 -0
  33. data/lib/steep/drivers/check.rb +53 -77
  34. data/lib/steep/drivers/scaffold.rb +303 -0
  35. data/lib/steep/drivers/utils/each_signature.rb +66 -0
  36. data/lib/steep/drivers/utils/validator.rb +115 -0
  37. data/lib/steep/drivers/validate.rb +39 -0
  38. data/lib/steep/errors.rb +291 -19
  39. data/lib/steep/interface/abstract.rb +44 -0
  40. data/lib/steep/interface/builder.rb +470 -0
  41. data/lib/steep/interface/instantiated.rb +126 -0
  42. data/lib/steep/interface/ivar_chain.rb +26 -0
  43. data/lib/steep/interface/method.rb +60 -0
  44. data/lib/steep/{interface.rb → interface/method_type.rb} +111 -100
  45. data/lib/steep/interface/substitution.rb +65 -0
  46. data/lib/steep/module_name.rb +116 -0
  47. data/lib/steep/parser.rb +1314 -814
  48. data/lib/steep/parser.y +536 -175
  49. data/lib/steep/source.rb +220 -25
  50. data/lib/steep/subtyping/check.rb +673 -0
  51. data/lib/steep/subtyping/constraints.rb +275 -0
  52. data/lib/steep/subtyping/relation.rb +41 -0
  53. data/lib/steep/subtyping/result.rb +126 -0
  54. data/lib/steep/subtyping/trace.rb +48 -0
  55. data/lib/steep/subtyping/variable_occurrence.rb +49 -0
  56. data/lib/steep/subtyping/variable_variance.rb +69 -0
  57. data/lib/steep/type_construction.rb +1630 -524
  58. data/lib/steep/type_inference/block_params.rb +100 -0
  59. data/lib/steep/type_inference/constant_env.rb +55 -0
  60. data/lib/steep/type_inference/send_args.rb +222 -0
  61. data/lib/steep/type_inference/type_env.rb +226 -0
  62. data/lib/steep/type_name.rb +27 -7
  63. data/lib/steep/typing.rb +4 -0
  64. data/lib/steep/version.rb +1 -1
  65. data/lib/steep.rb +71 -16
  66. data/smoke/and/a.rb +4 -2
  67. data/smoke/array/a.rb +4 -5
  68. data/smoke/array/b.rb +4 -4
  69. data/smoke/block/a.rb +2 -2
  70. data/smoke/block/a.rbi +2 -0
  71. data/smoke/block/b.rb +15 -0
  72. data/smoke/case/a.rb +3 -3
  73. data/smoke/class/a.rb +3 -3
  74. data/smoke/class/b.rb +0 -2
  75. data/smoke/class/d.rb +2 -2
  76. data/smoke/class/e.rb +1 -1
  77. data/smoke/class/f.rb +2 -2
  78. data/smoke/class/g.rb +8 -0
  79. data/smoke/const/a.rb +3 -3
  80. data/smoke/dstr/a.rb +1 -1
  81. data/smoke/ensure/a.rb +22 -0
  82. data/smoke/enumerator/a.rb +6 -6
  83. data/smoke/enumerator/b.rb +22 -0
  84. data/smoke/extension/a.rb +2 -2
  85. data/smoke/extension/b.rb +3 -3
  86. data/smoke/extension/c.rb +1 -1
  87. data/smoke/hello/hello.rb +2 -2
  88. data/smoke/if/a.rb +4 -2
  89. data/smoke/kwbegin/a.rb +8 -0
  90. data/smoke/literal/a.rb +5 -5
  91. data/smoke/method/a.rb +5 -5
  92. data/smoke/method/a.rbi +4 -0
  93. data/smoke/method/b.rb +29 -0
  94. data/smoke/module/a.rb +3 -3
  95. data/smoke/module/a.rbi +9 -0
  96. data/smoke/module/b.rb +2 -2
  97. data/smoke/module/c.rb +1 -1
  98. data/smoke/module/d.rb +5 -0
  99. data/smoke/module/e.rb +13 -0
  100. data/smoke/module/f.rb +13 -0
  101. data/smoke/rescue/a.rb +62 -0
  102. data/smoke/super/a.rb +2 -2
  103. data/smoke/type_case/a.rb +35 -0
  104. data/smoke/yield/a.rb +2 -2
  105. data/stdlib/builtin.rbi +463 -24
  106. data/steep.gemspec +3 -2
  107. metadata +91 -29
  108. data/lib/steep/annotation.rb +0 -223
  109. data/lib/steep/signature/class.rb +0 -450
  110. data/lib/steep/signature/extension.rb +0 -51
  111. data/lib/steep/signature/interface.rb +0 -49
  112. data/lib/steep/types/any.rb +0 -31
  113. data/lib/steep/types/class.rb +0 -27
  114. data/lib/steep/types/instance.rb +0 -27
  115. data/lib/steep/types/merge.rb +0 -32
  116. data/lib/steep/types/name.rb +0 -57
  117. data/lib/steep/types/union.rb +0 -42
  118. data/lib/steep/types/var.rb +0 -38
  119. data/lib/steep/types.rb +0 -4
data/lib/steep/errors.rb CHANGED
@@ -8,18 +8,49 @@ module Steep
8
8
  end
9
9
 
10
10
  def location_to_str
11
- "#{node.loc.expression.source_buffer.name}:#{node.loc.first_line}:#{node.loc.column}"
11
+ Rainbow("#{node.loc.expression.source_buffer.name}:#{node.loc.first_line}:#{node.loc.column}").red
12
+ end
13
+
14
+ def print_to(io)
15
+ source = node.loc.expression.source
16
+ io.puts "#{to_s} (#{Rainbow(source.split(/\n/).first).blue})"
17
+ end
18
+ end
19
+
20
+ module ResultPrinter
21
+ def print_result_to(io, level: 2)
22
+ indent = " " * level
23
+ result.trace.each do |s, t|
24
+ case s
25
+ when Interface::Method
26
+ io.puts "#{indent}#{s.name}(#{s.type_name}) <: #{t.name}(#{t.type_name})"
27
+ when Interface::MethodType
28
+ io.puts "#{indent}#{s} <: #{t} (#{s.location.name}:#{s.location.start_line})"
29
+ else
30
+ io.puts "#{indent}#{s} <: #{t}"
31
+ end
32
+ end
33
+ io.puts "#{indent} #{result.error.message}"
34
+ end
35
+
36
+ def print_to(io)
37
+ super
38
+ print_result_to io
12
39
  end
13
40
  end
14
41
 
15
42
  class IncompatibleAssignment < Base
16
43
  attr_reader :lhs_type
17
44
  attr_reader :rhs_type
45
+ attr_reader :result
46
+
47
+ include ResultPrinter
18
48
 
19
- def initialize(node:, lhs_type:, rhs_type:)
49
+ def initialize(node:, lhs_type:, rhs_type:, result:)
20
50
  super(node: node)
21
51
  @lhs_type = lhs_type
22
52
  @rhs_type = rhs_type
53
+ @result = result
23
54
  end
24
55
 
25
56
  def to_s
@@ -27,18 +58,66 @@ module Steep
27
58
  end
28
59
  end
29
60
 
61
+ class IncompatibleArguments < Base
62
+ attr_reader :node
63
+ attr_reader :receiver_type
64
+ attr_reader :method_type
65
+
66
+ def initialize(node:, receiver_type:, method_type:)
67
+ super(node: node)
68
+ @receiver_type = receiver_type
69
+ @method_type = method_type
70
+ end
71
+
72
+ def to_s
73
+ "#{location_to_str}: IncompatibleArguments: receiver=#{receiver_type}, method_type=#{method_type}"
74
+ end
75
+ end
76
+
30
77
  class ArgumentTypeMismatch < Base
31
- attr_reader :type
32
- attr_reader :method
78
+ attr_reader :node
79
+ attr_reader :expected
80
+ attr_reader :actual
81
+ attr_reader :receiver_type
33
82
 
34
- def initialize(node:, type:, method:)
83
+ def initialize(node:, receiver_type:, expected:, actual:)
35
84
  super(node: node)
36
- @type = type
37
- @method = method
85
+ @receiver_type = receiver_type
86
+ @expected = expected
87
+ @actual = actual
88
+ end
89
+
90
+ def to_s
91
+ "#{location_to_str}: ArgumentTypeMismatch: receiver=#{receiver_type}, expected=#{expected}, actual=#{actual}"
92
+ end
93
+ end
94
+
95
+ class IncompatibleBlockParameters < Base
96
+ attr_reader :node
97
+ attr_reader :method_type
98
+
99
+ def initialize(node:, method_type:)
100
+ super(node: node)
101
+ @method_type = method_type
102
+ end
103
+
104
+ def to_s
105
+ "#{location_to_str}: IncompatibleBlockParameters: method_type=#{method_type}"
106
+ end
107
+ end
108
+
109
+ class BlockParameterTypeMismatch < Base
110
+ attr_reader :expected
111
+ attr_reader :actual
112
+
113
+ def initialize(node:, expected:, actual:)
114
+ super(node: node)
115
+ @expected = expected
116
+ @actual = actual
38
117
  end
39
118
 
40
119
  def to_s
41
- "#{location_to_str}: ArgumentTypeMismatch: type=#{type}, method=#{method}"
120
+ "#{location_to_str}: BlockParameterTypeMismatch: expected=#{expected}, actual=#{actual}"
42
121
  end
43
122
  end
44
123
 
@@ -60,11 +139,15 @@ module Steep
60
139
  class ReturnTypeMismatch < Base
61
140
  attr_reader :expected
62
141
  attr_reader :actual
142
+ attr_reader :result
63
143
 
64
- def initialize(node:, expected:, actual:)
144
+ include ResultPrinter
145
+
146
+ def initialize(node:, expected:, actual:, result:)
65
147
  super(node: node)
66
148
  @expected = expected
67
149
  @actual = actual
150
+ @result = result
68
151
  end
69
152
 
70
153
  def to_s
@@ -73,24 +156,43 @@ module Steep
73
156
  end
74
157
 
75
158
  class UnexpectedBlockGiven < Base
76
- attr_reader :method
77
- attr_reader :type
159
+ attr_reader :method_type
78
160
 
79
- def initialize(node:, type:, method:)
161
+ def initialize(node:, method_type:)
80
162
  super(node: node)
81
- @type = type
82
- @method = method
163
+ @method_type = method_type
164
+ end
165
+
166
+ def to_s
167
+ "#{location_to_str}: UnexpectedBlockGiven: method_type=#{method_type.location&.source}"
168
+ end
169
+ end
170
+
171
+ class RequiredBlockMissing < Base
172
+ attr_reader :method_type
173
+
174
+ def initialize(node:, method_type:)
175
+ super(node: node)
176
+ @method_type = method_type
177
+ end
178
+
179
+ def to_s
180
+ "#{location_to_str}: RequiredBlockMissing: method_type=#{method_type.location&.source}"
83
181
  end
84
182
  end
85
183
 
86
184
  class BlockTypeMismatch < Base
87
185
  attr_reader :expected
88
186
  attr_reader :actual
187
+ attr_reader :result
89
188
 
90
- def initialize(node:, expected:, actual:)
189
+ include ResultPrinter
190
+
191
+ def initialize(node:, expected:, actual:, result:)
91
192
  super(node: node)
92
193
  @expected = expected
93
194
  @actual = actual
195
+ @result = result
94
196
  end
95
197
 
96
198
  def to_s
@@ -101,28 +203,103 @@ module Steep
101
203
  class BreakTypeMismatch < Base
102
204
  attr_reader :expected
103
205
  attr_reader :actual
206
+ attr_reader :result
104
207
 
105
- def initialize(node:, expected:, actual:)
208
+ include ResultPrinter
209
+
210
+ def initialize(node:, expected:, actual:, result:)
106
211
  super(node: node)
107
212
  @expected = expected
108
213
  @actual = actual
214
+ @result = result
215
+ end
216
+
217
+ def to_s
218
+ "#{location_to_str}: BreakTypeMismatch: expected=#{expected}, actual=#{actual}"
219
+ end
220
+ end
221
+
222
+ class UnexpectedJump < Base
223
+ def to_s
224
+ "#{location_to_str}: UnexpectedJump"
225
+ end
226
+ end
227
+
228
+ class UnexpectedJumpValue < Base
229
+ def to_s
230
+ "#{location_to_str}: UnexpectedJumpValue"
109
231
  end
110
232
  end
111
233
 
112
- class MethodParameterTypeMismatch < Base
234
+ class MethodArityMismatch < Base
113
235
  def to_s
114
- "#{location_to_str}: MethodParameterTypeMismatch: method=#{node.children[0]}"
236
+ "#{location_to_str}: MethodArityMismatch: method=#{node.children[0]}"
237
+ end
238
+ end
239
+
240
+ class IncompatibleMethodTypeAnnotation < Base
241
+ attr_reader :interface_method
242
+ attr_reader :annotation_method
243
+ attr_reader :result
244
+
245
+ include ResultPrinter
246
+
247
+ def initialize(node:, interface_method:, annotation_method:, result:)
248
+ super(node: node)
249
+ @interface_method = interface_method
250
+ @annotation_method = annotation_method
251
+ @result = result
252
+ end
253
+
254
+ def to_s
255
+ "#{location_to_str}: IncompatibleMethodTypeAnnotation: interface_method=#{interface_method.type_name}.#{interface_method.name}, annotation_method=#{annotation_method.name}"
256
+ end
257
+ end
258
+
259
+ class MethodDefinitionWithOverloading < Base
260
+ attr_reader :method
261
+
262
+ def initialize(node:, method:)
263
+ super(node: node)
264
+ @method = method
265
+ end
266
+
267
+ def to_s
268
+ "#{location_to_str}: MethodDefinitionWithOverloading: method=#{method.name}, types=#{method.types.join(" | ")}"
269
+ end
270
+ end
271
+
272
+ class MethodReturnTypeAnnotationMismatch < Base
273
+ attr_reader :method_type
274
+ attr_reader :annotation_type
275
+ attr_reader :result
276
+
277
+ include ResultPrinter
278
+
279
+ def initialize(node:, method_type:, annotation_type:, result:)
280
+ super(node: node)
281
+ @method_type = method_type
282
+ @annotation_type = annotation_type
283
+ @result = result
284
+ end
285
+
286
+ def to_s
287
+ "#{location_to_str}: MethodReturnTypeAnnotationMismatch: method_type=#{method_type.return_type}, annotation_type=#{annotation_type}"
115
288
  end
116
289
  end
117
290
 
118
291
  class MethodBodyTypeMismatch < Base
119
292
  attr_reader :expected
120
293
  attr_reader :actual
294
+ attr_reader :result
121
295
 
122
- def initialize(node:, expected:, actual:)
296
+ include ResultPrinter
297
+
298
+ def initialize(node:, expected:, actual:, result:)
123
299
  super(node: node)
124
300
  @expected = expected
125
301
  @actual = actual
302
+ @result = result
126
303
  end
127
304
 
128
305
  def to_s
@@ -194,6 +371,19 @@ module Steep
194
371
  end
195
372
  end
196
373
 
374
+ class UnknownConstantAssigned < Base
375
+ attr_reader :type
376
+
377
+ def initialize(node:, type:)
378
+ super(node: node)
379
+ @type = type
380
+ end
381
+
382
+ def to_s
383
+ "#{location_to_str}: UnknownConstantAssigned: type=#{type}"
384
+ end
385
+ end
386
+
197
387
  class FallbackAny < Base
198
388
  def initialize(node:)
199
389
  @node = node
@@ -203,5 +393,87 @@ module Steep
203
393
  "#{location_to_str}: FallbackAny"
204
394
  end
205
395
  end
396
+
397
+ class UnsatisfiableConstraint < Base
398
+ attr_reader :method_type
399
+ attr_reader :var
400
+ attr_reader :sub_type
401
+ attr_reader :super_type
402
+ attr_reader :result
403
+
404
+ def initialize(node:, method_type:, var:, sub_type:, super_type:, result:)
405
+ super(node: node)
406
+ @method_type = method_type
407
+ @var = var
408
+ @sub_type = sub_type
409
+ @super_type = super_type
410
+ @result = result
411
+ end
412
+
413
+ include ResultPrinter
414
+
415
+ def to_s
416
+ "#{location_to_str}: UnsatisfiableConstraint: method_type=#{method_type}, constraint=#{sub_type} <: '#{var} <: #{super_type}"
417
+ end
418
+ end
419
+
420
+ class IncompatibleAnnotation < Base
421
+ attr_reader :var_name
422
+ attr_reader :result
423
+ attr_reader :relation
424
+
425
+ def initialize(node:, var_name:, result:, relation:)
426
+ super(node: node)
427
+ @var_name = var_name
428
+ @result = result
429
+ @relation = relation
430
+ end
431
+
432
+ include ResultPrinter
433
+
434
+ def to_s
435
+ "#{location_to_str}: IncompatibleAnnotation: var_name=#{var_name}, #{relation}"
436
+ end
437
+ end
438
+
439
+ class IncompatibleTypeCase < Base
440
+ attr_reader :var_name
441
+ attr_reader :result
442
+ attr_reader :relation
443
+
444
+ def initialize(node:, var_name:, result:, relation:)
445
+ super(node: node)
446
+ @var_name = var_name
447
+ @result = result
448
+ @relation = relation
449
+ end
450
+
451
+ include ResultPrinter
452
+
453
+ def to_s
454
+ "#{location_to_str}: IncompatibleTypeCase: var_name=#{var_name}, #{relation}"
455
+ end
456
+ end
457
+
458
+ class ElseOnExhaustiveCase < Base
459
+ def initialize(node:, type:)
460
+ def to_s
461
+ "#{location_to_str}: ElseOnExhaustiveCase: type=#{type}"
462
+ end
463
+ end
464
+ end
465
+
466
+ class UnexpectedSplat < Base
467
+ attr_reader :type
468
+
469
+ def initialize(node:, type:)
470
+ super(node: node)
471
+ @type = type
472
+ end
473
+
474
+ def to_s
475
+ "#{location_to_str}: UnexpectedSplat: type=#{type}"
476
+ end
477
+ end
206
478
  end
207
479
  end
@@ -0,0 +1,44 @@
1
+ module Steep
2
+ module Interface
3
+ class Abstract
4
+ attr_reader :name
5
+ attr_reader :kind
6
+ attr_reader :params
7
+ attr_reader :methods
8
+ attr_reader :supers
9
+ attr_reader :ivar_chains
10
+
11
+ def initialize(name:, params:, methods:, supers:, ivar_chains:)
12
+ @name = name
13
+ @params = params
14
+ @methods = methods
15
+ @supers = supers
16
+ @ivar_chains = ivar_chains
17
+ end
18
+
19
+ def ivars
20
+ @ivars ||= ivar_chains.transform_values(&:type)
21
+ end
22
+
23
+ def ==(other)
24
+ other.is_a?(self.class) &&
25
+ other.name == name &&
26
+ other.params == params &&
27
+ other.methods == methods &&
28
+ other.supers == supers &&
29
+ other.ivars == ivars
30
+ end
31
+
32
+ def instantiate(type:, args:, instance_type:, module_type:)
33
+ Steep.logger.debug("type=#{type}, self=#{name}, args=#{args}, params=#{params}")
34
+ subst = Substitution.build(params, args, instance_type: instance_type, module_type: module_type, self_type: type)
35
+
36
+ Instantiated.new(
37
+ type: type,
38
+ methods: methods.transform_values {|method| method.subst(subst) },
39
+ ivar_chains: ivar_chains.transform_values {|chain| chain.subst(subst) }
40
+ )
41
+ end
42
+ end
43
+ end
44
+ end