steep 0.1.0.pre → 0.1.0.pre2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +72 -51
- data/bin/smoke_runner.rb +6 -2
- data/lib/steep/cli.rb +4 -4
- data/lib/steep/drivers/check.rb +4 -0
- data/lib/steep/interface.rb +11 -4
- data/lib/steep/parser.y +23 -5
- data/lib/steep/signature/class.rb +118 -26
- data/lib/steep/signature/errors.rb +28 -0
- data/lib/steep/signature/interface.rb +2 -1
- data/lib/steep/type_assignability.rb +13 -8
- data/lib/steep/type_construction.rb +41 -6
- data/lib/steep/type_name.rb +31 -1
- data/lib/steep/types/name.rb +2 -2
- data/lib/steep/version.rb +1 -1
- data/sig/signature.rbi +92 -0
- data/smoke/array/b.rb +16 -0
- data/smoke/class/a.rbi +15 -0
- data/smoke/class/d.rb +9 -0
- data/smoke/class/e.rb +12 -0
- data/smoke/class/f.rb +8 -0
- data/smoke/enumerator/a.rb +19 -0
- data/smoke/initialize/a.rb +12 -0
- data/smoke/initialize/a.rbi +3 -0
- data/smoke/module/a.rb +1 -1
- data/smoke/module/c.rb +23 -0
- data/stdlib/builtin.rbi +19 -4
- data/steep.gemspec +2 -0
- metadata +12 -4
@@ -22,6 +22,10 @@ module Steep
|
|
22
22
|
super(signature: signature)
|
23
23
|
@type = type
|
24
24
|
end
|
25
|
+
|
26
|
+
def puts(io)
|
27
|
+
io.puts "UnknownTypeName: signature=#{signature.name}, type=#{type}"
|
28
|
+
end
|
25
29
|
end
|
26
30
|
|
27
31
|
class IncompatibleOverride < Base
|
@@ -40,6 +44,10 @@ module Steep
|
|
40
44
|
@this_method = this_method
|
41
45
|
@super_method = super_method
|
42
46
|
end
|
47
|
+
|
48
|
+
def puts(io)
|
49
|
+
io.puts "IncompatibleOverride: signature=#{signature.name}, method=#{method_name}"
|
50
|
+
end
|
43
51
|
end
|
44
52
|
|
45
53
|
class InvalidTypeApplication < Base
|
@@ -51,6 +59,10 @@ module Steep
|
|
51
59
|
@type_name = type_name
|
52
60
|
@type_args = type_args
|
53
61
|
end
|
62
|
+
|
63
|
+
def puts(io)
|
64
|
+
io.puts "InvalidTypeApplication: signature=#{signature.name}, type_name=#{type_name}, type_args=#{type_args}"
|
65
|
+
end
|
54
66
|
end
|
55
67
|
|
56
68
|
class InvalidSelfType < Base
|
@@ -60,6 +72,11 @@ module Steep
|
|
60
72
|
super(signature: signature)
|
61
73
|
@member = member
|
62
74
|
end
|
75
|
+
|
76
|
+
|
77
|
+
def puts(io)
|
78
|
+
io.puts "InvalidSelfType: signature=#{signature.name}, module=#{member.name}"
|
79
|
+
end
|
63
80
|
end
|
64
81
|
|
65
82
|
class UnexpectedTypeNameKind < Base
|
@@ -71,6 +88,17 @@ module Steep
|
|
71
88
|
@type = type
|
72
89
|
@expected_kind = expected_kind
|
73
90
|
end
|
91
|
+
|
92
|
+
|
93
|
+
def puts(io)
|
94
|
+
io.puts "UnexpectedTypeNameKind: signature=#{signature.name}, type=#{type}, kind=#{expected_kind}"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
class ConstructorNoCheck < Base
|
99
|
+
def puts(io)
|
100
|
+
io.puts "ConstructorNoCheck: signature=#{signature.name}"
|
101
|
+
end
|
74
102
|
end
|
75
103
|
end
|
76
104
|
end
|
@@ -32,11 +32,12 @@ module Steep
|
|
32
32
|
# @type var map: Hash<Symbol, Steep__Type>
|
33
33
|
map = Hash[self.params.zip(params)]
|
34
34
|
Steep::Interface.new(name: name,
|
35
|
+
params: params,
|
35
36
|
methods: methods.transform_values {|method|
|
36
37
|
types = method.map {|method_type|
|
37
38
|
method_type.substitute(klass: klass, instance: instance, params: map)
|
38
39
|
}
|
39
|
-
Steep::Interface::Method.new(types: types, super_method: nil)
|
40
|
+
Steep::Interface::Method.new(types: types, super_method: nil, attributes: [])
|
40
41
|
})
|
41
42
|
end
|
42
43
|
|
@@ -70,7 +70,7 @@ module Steep
|
|
70
70
|
end
|
71
71
|
|
72
72
|
def test_interface(src, dest, known_pairs)
|
73
|
-
if src
|
73
|
+
if src == dest
|
74
74
|
return true
|
75
75
|
end
|
76
76
|
|
@@ -140,7 +140,7 @@ module Steep
|
|
140
140
|
assigning_pairs << [src.rest, dest_type.last]
|
141
141
|
end
|
142
142
|
end
|
143
|
-
when src.required.size + src.optional.size >= dest.required.size + dest.optional.size
|
143
|
+
when src.required.size + src.optional.size >= dest.required.size + dest.optional.size
|
144
144
|
while src_flat.size > 0
|
145
145
|
src_type = src_flat.shift
|
146
146
|
dest_type = dest_flat.shift
|
@@ -148,7 +148,11 @@ module Steep
|
|
148
148
|
if dest_type
|
149
149
|
assigning_pairs << [src_type.last, dest_type.last]
|
150
150
|
else
|
151
|
-
|
151
|
+
if src_type.first == :required
|
152
|
+
return false
|
153
|
+
else
|
154
|
+
break
|
155
|
+
end
|
152
156
|
end
|
153
157
|
end
|
154
158
|
else
|
@@ -216,7 +220,7 @@ module Steep
|
|
216
220
|
test(src: dest.return_type, dest: src.return_type, known_pairs: known_pairs)
|
217
221
|
end
|
218
222
|
|
219
|
-
def resolve_interface(name, params, klass: nil, instance: nil)
|
223
|
+
def resolve_interface(name, params, klass: nil, instance: nil, constructor: nil)
|
220
224
|
klass ||= Types::Name.module(name: name.name, params: params)
|
221
225
|
instance ||= Types::Name.instance(name: name.name, params: params)
|
222
226
|
|
@@ -225,10 +229,10 @@ module Steep
|
|
225
229
|
signatures[name.name].to_interface(klass: klass, instance: instance, params: params)
|
226
230
|
when TypeName::Instance
|
227
231
|
methods = signatures[name.name].instance_methods(assignability: self, klass: klass, instance: instance, params: params)
|
228
|
-
Interface.new(name: name, methods: methods)
|
232
|
+
Interface.new(name: name, params: params, methods: methods.reject {|key, _| key == :initialize })
|
229
233
|
when TypeName::Module
|
230
|
-
methods = signatures[name.name].module_methods(assignability: self, klass: klass, instance: instance, params: params)
|
231
|
-
Interface.new(name: name, methods: methods)
|
234
|
+
methods = signatures[name.name].module_methods(assignability: self, klass: klass, instance: instance, params: params, constructor: constructor)
|
235
|
+
Interface.new(name: name, params: params, methods: methods)
|
232
236
|
else
|
233
237
|
raise "Unexpected type name: #{name.inspect}"
|
234
238
|
end
|
@@ -284,7 +288,8 @@ module Steep
|
|
284
288
|
}
|
285
289
|
method = methods[name]
|
286
290
|
when Types::Name
|
287
|
-
|
291
|
+
constructor = type.name.is_a?(TypeName::Module) && type.name.constructor
|
292
|
+
interface = resolve_interface(type.name, type.params, constructor: constructor)
|
288
293
|
method = interface.methods[name]
|
289
294
|
else
|
290
295
|
raise "Unexpected type: #{type}"
|
@@ -3,12 +3,14 @@ module Steep
|
|
3
3
|
class MethodContext
|
4
4
|
attr_reader :name
|
5
5
|
attr_reader :method
|
6
|
+
attr_reader :constructor
|
6
7
|
|
7
|
-
def initialize(name:, method:, method_type:, return_type:)
|
8
|
+
def initialize(name:, method:, method_type:, return_type:, constructor:)
|
8
9
|
@name = name
|
9
10
|
@method = method
|
10
11
|
@return_type = return_type
|
11
12
|
@method_type = method_type
|
13
|
+
@constructor = constructor
|
12
14
|
end
|
13
15
|
|
14
16
|
def return_type
|
@@ -87,7 +89,7 @@ module Steep
|
|
87
89
|
end
|
88
90
|
|
89
91
|
if (type = annotations.lookup_method_type(method_name))
|
90
|
-
Interface::Method.new(types: [type], super_method: entry&.super_method)
|
92
|
+
Interface::Method.new(types: [type], super_method: entry&.super_method, attributes: [])
|
91
93
|
else
|
92
94
|
entry
|
93
95
|
end
|
@@ -110,11 +112,15 @@ module Steep
|
|
110
112
|
var_types = {}
|
111
113
|
end
|
112
114
|
|
115
|
+
# FIXME: reading signature directory does not look good...
|
116
|
+
constructor_method = entry&.attributes&.include?(:constructor)
|
117
|
+
|
113
118
|
method_context = MethodContext.new(
|
114
119
|
name: method_name,
|
115
120
|
method: entry,
|
116
121
|
method_type: annotations.lookup_method_type(method_name),
|
117
122
|
return_type: annots.return_type,
|
123
|
+
constructor: constructor_method
|
118
124
|
)
|
119
125
|
|
120
126
|
ivar_types = annots.ivar_types.keys.each.with_object({}) do |var, env|
|
@@ -213,7 +219,18 @@ module Steep
|
|
213
219
|
end
|
214
220
|
|
215
221
|
when :send
|
216
|
-
|
222
|
+
if self_class?(node)
|
223
|
+
module_type = module_context.module_type
|
224
|
+
type = if module_type.is_a?(Types::Name)
|
225
|
+
Types::Name.new(name: module_type.name.updated(constructor: method_context.constructor),
|
226
|
+
params: module_type.params)
|
227
|
+
else
|
228
|
+
module_type
|
229
|
+
end
|
230
|
+
typing.add_typing(node, type)
|
231
|
+
else
|
232
|
+
type_send(node, with_block: false)
|
233
|
+
end
|
217
234
|
|
218
235
|
when :super
|
219
236
|
if self_type && method_context&.method
|
@@ -449,6 +466,8 @@ module Steep
|
|
449
466
|
when :module
|
450
467
|
annots = source.annotations(block: node)
|
451
468
|
|
469
|
+
module_type = Types::Name.instance(name: :Module)
|
470
|
+
|
452
471
|
if annots.implement_module
|
453
472
|
signature = assignability.signatures[annots.implement_module]
|
454
473
|
raise "Module instance should be an module: #{annots.instance_type || annots.implment_module}" unless signature.is_a?(Signature::Module)
|
@@ -456,19 +475,31 @@ module Steep
|
|
456
475
|
ty = Types::Name.instance(name: annots.implement_module)
|
457
476
|
|
458
477
|
if signature.self_type
|
459
|
-
instance_type = Types::Merge.new(types: [
|
478
|
+
instance_type = Types::Merge.new(types: [Types::Name.instance(name: :Object),
|
479
|
+
signature.self_type,
|
480
|
+
ty])
|
460
481
|
else
|
461
|
-
instance_type =
|
482
|
+
instance_type = Types::Merge.new(types: [Types::Name.instance(name: :Object),
|
483
|
+
ty])
|
462
484
|
end
|
485
|
+
|
486
|
+
module_type = Types::Merge.new(types: [
|
487
|
+
Types::Name.instance(name: :Module),
|
488
|
+
Types::Name.module(name: annots.implement_module)
|
489
|
+
])
|
463
490
|
end
|
464
491
|
|
465
492
|
if annots.instance_type
|
466
493
|
instance_type = annots.instance_type
|
467
494
|
end
|
468
495
|
|
496
|
+
if annots.module_type
|
497
|
+
module_type = annots.module_type
|
498
|
+
end
|
499
|
+
|
469
500
|
module_context_ = ModuleContext.new(
|
470
501
|
instance_type: instance_type,
|
471
|
-
module_type:
|
502
|
+
module_type: module_type,
|
472
503
|
const_types: annots.const_types
|
473
504
|
)
|
474
505
|
|
@@ -989,5 +1020,9 @@ module Steep
|
|
989
1020
|
typing.add_error Errors::FallbackAny.new(node: node)
|
990
1021
|
typing.add_typing node, Types::Any.new
|
991
1022
|
end
|
1023
|
+
|
1024
|
+
def self_class?(node)
|
1025
|
+
node.type == :send && node.children[0]&.type == :self && node.children[1] == :class
|
1026
|
+
end
|
992
1027
|
end
|
993
1028
|
end
|
data/lib/steep/type_name.rb
CHANGED
@@ -27,8 +27,38 @@ module Steep
|
|
27
27
|
class Interface < Base; end
|
28
28
|
|
29
29
|
class Module < Base
|
30
|
+
attr_reader :constructor
|
31
|
+
|
30
32
|
def to_s
|
31
|
-
|
33
|
+
k = case constructor
|
34
|
+
when nil
|
35
|
+
""
|
36
|
+
when true
|
37
|
+
" constructor"
|
38
|
+
when false
|
39
|
+
" noconstructor"
|
40
|
+
end
|
41
|
+
|
42
|
+
"#{name}.module#{k}"
|
43
|
+
end
|
44
|
+
|
45
|
+
def initialize(name:, constructor:)
|
46
|
+
super(name: name)
|
47
|
+
@constructor = constructor
|
48
|
+
end
|
49
|
+
|
50
|
+
def ==(other)
|
51
|
+
other.is_a?(self.class) && other.name == name && other.constructor == constructor
|
52
|
+
end
|
53
|
+
|
54
|
+
NOTHING = Object.new
|
55
|
+
|
56
|
+
def updated(constructor: NOTHING)
|
57
|
+
if NOTHING == constructor
|
58
|
+
constructor = self.constructor
|
59
|
+
end
|
60
|
+
|
61
|
+
self.class.new(name: name, constructor: constructor)
|
32
62
|
end
|
33
63
|
end
|
34
64
|
|
data/lib/steep/types/name.rb
CHANGED
@@ -21,8 +21,8 @@ module Steep
|
|
21
21
|
self.new(name: TypeName::Interface.new(name: name), params: params)
|
22
22
|
end
|
23
23
|
|
24
|
-
def self.module(name:, params: [])
|
25
|
-
self.new(name: TypeName::Module.new(name: name), params: params)
|
24
|
+
def self.module(name:, params: [], constructor: nil)
|
25
|
+
self.new(name: TypeName::Module.new(name: name, constructor: constructor), params: params)
|
26
26
|
end
|
27
27
|
|
28
28
|
def self.instance(name:, params: [])
|
data/lib/steep/version.rb
CHANGED
data/sig/signature.rbi
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
class Steep__Signature__Error
|
2
2
|
def initialize: (signature: Steep__Signature) -> any
|
3
3
|
def signature: -> Steep__Signature
|
4
|
+
def puts: (any) -> any
|
4
5
|
end
|
5
6
|
|
6
7
|
class Steep__Signature__Errors__UnknownTypeName <: Steep__Signature__Error
|
@@ -8,8 +9,21 @@ class Steep__Signature__Errors__UnknownTypeName <: Steep__Signature__Error
|
|
8
9
|
def type: -> Steep__Type
|
9
10
|
end
|
10
11
|
|
12
|
+
class Steep__BlockType
|
13
|
+
def params: -> Steep__MethodParams
|
14
|
+
def return_type: -> Steep__Type
|
15
|
+
end
|
16
|
+
|
17
|
+
class Steep__MethodParams
|
18
|
+
def each_type: { (Steep__Type) -> any } -> instance
|
19
|
+
end
|
20
|
+
|
11
21
|
class Steep__MethodType
|
12
22
|
def substitute: (klass: Steep__Type, instance: Steep__Type, params: Hash<Symbol, Steep__Type>) -> Steep__MethodType
|
23
|
+
def updated: (?type_params: Array<Symbol>, ?params: Steep__MethodParams, ?block: any, ?return_type: Steep__Type) -> Steep__MethodType
|
24
|
+
def params: -> Steep__MethodParams
|
25
|
+
def return_type: -> Steep__Type
|
26
|
+
def block: -> Steep__BlockType
|
13
27
|
end
|
14
28
|
|
15
29
|
class Steep__Interface
|
@@ -19,6 +33,7 @@ end
|
|
19
33
|
class Steep__Method
|
20
34
|
def initialize: (types: Array<Steep__MethodType>, super_method: Steep__Method) -> any
|
21
35
|
def substitute: (klass: Steep__Type, instance: Steep__Type, params: Hash<Symbol, Steep__Type>) -> Steep__Method
|
36
|
+
def types: -> Array<Steep__MethodType>
|
22
37
|
end
|
23
38
|
|
24
39
|
class Steep__Signature
|
@@ -34,6 +49,83 @@ class Steep__Signature__Errors__IncompatibleOverride <: Steep__Signature__Error
|
|
34
49
|
def super_method: -> Steep__Method
|
35
50
|
end
|
36
51
|
|
52
|
+
class Steep__SignatureMember__Method <: Steep__Signature__Member
|
53
|
+
def initialize: (name: Symbol, types: Array<Steep__MethodType>) -> any
|
54
|
+
def name: -> Symbol
|
55
|
+
def types: -> Array<Steep__MethodType>
|
56
|
+
end
|
57
|
+
|
58
|
+
class Steep__SignatureMember__Include <: Steep__Signature__Member
|
59
|
+
def initialize: (name: Symbol) -> any
|
60
|
+
def name: -> Symbol
|
61
|
+
end
|
62
|
+
|
63
|
+
class Steep__SignatureMember__Extend <: Steep__Signature__Member
|
64
|
+
def initialize: (name: Symbol) -> any
|
65
|
+
def name: -> Symbol
|
66
|
+
end
|
67
|
+
|
68
|
+
interface _Steep__SignatureMember__Mixin
|
69
|
+
def name: -> Steep__Type
|
70
|
+
end
|
71
|
+
|
72
|
+
interface _Steep__WithMethods
|
73
|
+
def instance_methods: (assignability: any, klass: Steep__Type, instance: Steep__Type, params: Array<Steep__Type>) -> Hash<Symbol, Steep__Method>
|
74
|
+
def module_methods: (assignability: any, klass: Steep__Type, instance: Steep__Type, params: Array<Steep__Type>) -> Hash<Symbol, Steep__Method>
|
75
|
+
def type_application_hash: (Array<Steep__Type>) -> Hash<Symbol, Steep__Type>
|
76
|
+
def members: -> Array<Steep__Signature__Member>
|
77
|
+
def is_class?: -> _Boolean
|
78
|
+
end
|
79
|
+
|
80
|
+
module Steep__Signature__WithMethods : _Steep__WithMethods
|
81
|
+
def instance_methods: (assignability: any, klass: Steep__Type, instance: Steep__Type, params: Array<Steep__Type>) -> Hash<Symbol, Steep__Method>
|
82
|
+
def module_methods: (assignability: any, klass: Steep__Type, instance: Steep__Type, params: Array<Steep__Type>) -> Hash<Symbol, Steep__Method>
|
83
|
+
def merge_methods: (Hash<Symbol, Steep__Method>, Hash<Symbol, Steep__Method>) -> Hash<Symbol, Steep__Method>
|
84
|
+
end
|
85
|
+
|
86
|
+
interface _Steep__WithMembers
|
87
|
+
def members: -> Array<Steep__Signature__Member>
|
88
|
+
def params: -> Array<Symbol>
|
89
|
+
end
|
90
|
+
|
91
|
+
module Steep__Signature__WithMembers : _Steep__WithMembers
|
92
|
+
def each_type: { (Steep__Type) -> any } -> any
|
93
|
+
def validate_mixins: (any, Steep__Interface) -> any
|
94
|
+
end
|
95
|
+
|
96
|
+
interface _Steep__WithParams
|
97
|
+
end
|
98
|
+
|
99
|
+
module Steep__Signature__WithParams : _Steep__WithParams
|
100
|
+
def type_application_hash: (Array<Steep__Type>) -> Hash<Symbol, Steep__Type>
|
101
|
+
end
|
102
|
+
|
103
|
+
class Steep__Signature__Module
|
104
|
+
include Steep__Signature__WithMethods
|
105
|
+
include Steep__Signature__WithMembers
|
106
|
+
include Steep__Signature__WithParams
|
107
|
+
|
108
|
+
def initialize: (name: Symbol, params: Array<Symbol>, members: Array<Steep__Signature__Member>, self_type: Steep__Type) -> any
|
109
|
+
def name: -> Symbol
|
110
|
+
def params: -> Array<Symbol>
|
111
|
+
def members: -> Array<Steep__Signature__Member>
|
112
|
+
def self_type: -> Steep__Type
|
113
|
+
def is_class?: -> _Boolean
|
114
|
+
end
|
115
|
+
|
116
|
+
class Steep__Signature__Class
|
117
|
+
include Steep__Signature__WithMethods
|
118
|
+
include Steep__Signature__WithMembers
|
119
|
+
include Steep__Signature__WithParams
|
120
|
+
|
121
|
+
def initialize: (name: Symbol, params: Array<Symbol>, members: Array<Steep__Signature__Member>, super_class: Steep__Types__Name) -> any
|
122
|
+
def name: -> Symbol
|
123
|
+
def params: -> Array<Symbol>
|
124
|
+
def members: -> Array<Steep__Signature__Member>
|
125
|
+
def super_class: -> Steep__Types__Name
|
126
|
+
def is_class?: -> _Boolean
|
127
|
+
end
|
128
|
+
|
37
129
|
class Steep__Signature__Extension
|
38
130
|
def initialize: (module_name: Symbol, extension_name: Symbol, members: Array<Steep__Signature__Member>) -> any
|
39
131
|
def module_name: -> Symbol
|
data/smoke/array/b.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
x = ""
|
2
|
+
y = 1
|
3
|
+
|
4
|
+
# !expects IncompatibleAssignment: lhs_type=String, rhs_type=Integer
|
5
|
+
x = y
|
6
|
+
# !expects IncompatibleAssignment: lhs_type=Integer, rhs_type=String
|
7
|
+
y = x
|
8
|
+
|
9
|
+
# @type var a: Array<Integer>
|
10
|
+
# @type var b: Array<String>
|
11
|
+
|
12
|
+
a = []
|
13
|
+
# !expects IncompatibleAssignment: lhs_type=Array<String>, rhs_type=Array<Integer>
|
14
|
+
b = a
|
15
|
+
# !expects IncompatibleAssignment: lhs_type=Array<Integer>, rhs_type=Array<String>
|
16
|
+
a = b
|
data/smoke/class/a.rbi
CHANGED
@@ -7,3 +7,18 @@ end
|
|
7
7
|
class B
|
8
8
|
def name: -> String
|
9
9
|
end
|
10
|
+
|
11
|
+
class C
|
12
|
+
def (constructor) foo: -> instance
|
13
|
+
def bar: -> instance
|
14
|
+
end
|
15
|
+
|
16
|
+
class D
|
17
|
+
def initialize: (String) -> any
|
18
|
+
def foo: -> any
|
19
|
+
end
|
20
|
+
|
21
|
+
class E
|
22
|
+
def initialize: () -> any
|
23
|
+
def foo: -> any
|
24
|
+
end
|