steep 0.1.0.pre → 0.1.0.pre2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 91398a985c422d844373a28dadd59f8e55b73e8f
4
- data.tar.gz: bdf3272c32938f7b5e762cfffce099b26630115b
3
+ metadata.gz: 74822cb390656501c900a6a8c1cb9fbe60c4dc4c
4
+ data.tar.gz: 1bd94c67e5339288af5052ecdbfaa553ae151aee
5
5
  SHA512:
6
- metadata.gz: 1345b14455a625814b4beafcab5ad3327f47b2dd0be200a5ecbc73157c83ab8074b6069a80acffb8fe563987c042f133820c33c07d1a7baa4039d29e35438735
7
- data.tar.gz: 455b3c6502ef94579bb859f12cbaca314285f426cf1a0b3cf5a9cad0c1533664738f8674b20ebde46ef8b8fcaa443ace1ece38f57922e5427465771afbf98f77
6
+ metadata.gz: 8102354b9e6ca837f22439b9b721e6e7ec67bc4b2e49de5db26a59d7167d5399ba04183b2e88d49afa3bf20cb88e5ed94ce6363a22caa0e7b5ec88ffd9963dfd
7
+ data.tar.gz: ea2304c8ee9850fc540c0b656daf4b100c97de914a4a124e332ef53117b0aa137c6f05a62402227a4601d51a74b1b5298c64980a6e3be9af300f480e41045e0a
data/README.md CHANGED
@@ -2,86 +2,107 @@
2
2
 
3
3
  ## Installation
4
4
 
5
- Add this line to your application's Gemfile:
5
+ Install via RubyGems.
6
6
 
7
- ```ruby
8
- gem 'steep'
9
- ```
10
-
11
- And then execute:
7
+ $ gem install steep --pre
12
8
 
13
- $ bundle
9
+ Note that Steep is not released yet (pre-released). Add `--pre` for `gem install`.
14
10
 
15
- Or install it yourself as:
11
+ ### Requirements
16
12
 
17
- $ gem install steep
13
+ Steep requires Ruby 2.4.
18
14
 
19
15
  ## Usage
20
16
 
21
- Run `steep check` command in project dir.
17
+ Steep does not infer types from Ruby programs, but requires declaring types and writing annotations.
18
+ You have to go on the following three steps.
22
19
 
23
- ```
24
- $ steep check
25
- $ steep check lib
26
- ```
20
+ ### 1. Declare Signatures
27
21
 
28
- It loads signatures from the global registry and `sig` dir in current dir.
29
- If you want to load signuatres from dir different from `sig`, pass `-I` parameter.
22
+ Declare signatures in `.rbi` files.
30
23
 
31
24
  ```
32
- $ steep check -I signauture -I sig .
33
- ```
25
+ interface _Foo {
26
+ def do_something: (String) -> any
27
+ }
34
28
 
35
- Note that when `-I` option is given, `steep` does not load signatures from `sig` dir.
29
+ module Fooable : _Foo {
30
+ def foo: (Array<String>) { (String) -> String } -> any
31
+ }
36
32
 
37
- ## Type Annotations
33
+ class SuperFoo {
34
+ include Fooable
38
35
 
39
- You have to write type annotations in your Ruby program.
36
+ def name: -> String
37
+ def do_something: (String) -> any
38
+ def bar: (?Symbol, size: Integer) -> Symbol
39
+ }
40
+ ```
40
41
 
41
- ```rb
42
- # @import ActiveRecord.Try
42
+ ### 2. Annotate Ruby Code
43
43
 
44
+ Write annotations to your Ruby code.
45
+
46
+ ```rb
44
47
  class Foo
45
- # @class Foo<A> extends Object
46
-
47
- # @attribute results: (readonly) Array<A>
48
- attr_reader :results
49
-
50
- # @type initialize: () -> _
51
- def initialize()
52
- @results = []
48
+ # @implements SuperFoo
49
+ # @type const Helper: FooHelper
50
+
51
+ # @dynamic name
52
+ attr_reader :name
53
+
54
+ def do_something(string)
55
+ # ...
53
56
  end
54
-
55
- # @type plus: (Addable<X, A>, X) -> A
56
- def plus(x, y)
57
- (x + y).try do |a|
58
- results << a
59
- a
60
- end
57
+
58
+ def bar(symbol = :default, size:)
59
+ Helper.run_bar(symbol, size: size)
61
60
  end
62
61
  end
63
62
  ```
64
63
 
65
- ## Signature
66
-
67
- Steep does not allow types to be constructed from Ruby programs.
68
- You have to write down signatures by yourself.
64
+ ### 3. Type Check
69
65
 
70
- ### Signature Scaffolding
71
-
72
- Steep allows generate a *scaffold* from Ruby programs.
66
+ Run `steep check` command to type check.
73
67
 
74
68
  ```
75
- $ steep scaffold lib/**/*.rb
69
+ $ steep check lib/foo.rb
70
+ foo.rb:41:18: NoMethodError: type=FooHelper, method=run_bar
71
+ foo.rb:42:24: NoMethodError: type=String, method==~
76
72
  ```
77
73
 
78
- The generated scaffold includes:
74
+ ## Commandline
75
+
76
+ `steep check` is the command to run type checking.
77
+
78
+ ### Signature Directory
79
+
80
+ Use `-I` option to specify signature file or signature directory.
81
+
82
+ $ steep check -I my-types.rbi test.rb
83
+
84
+ If you don't specify `-I` option, it assumes `sig` directory.
85
+
86
+ ### Detecting Fallback
87
+
88
+ When Steep finds a node which cannot be typed, it assumes the type of the node is *any*.
89
+ *any* type does not raise any type error so that fallback to *any* may hide some type errors.
90
+
91
+ Using `--fallback-any-is-error` option prints the fallbacks.
92
+
93
+ $ steep check --fallback-any-is-error test.rb
94
+
95
+ ### Dump All Types
96
+
97
+ When you are debugging, printing all types of all node in the source code may help.
98
+
99
+ Use `--dump-all-types` for that.
79
100
 
80
- * Signature definition for each class/module defined in the given program
81
- * Method definition stub for each method
101
+ $ steep check --dump-all-types test.rb
82
102
 
83
- The scaffold may be a good starting point for writing signatures.
103
+ ## Examples
84
104
 
105
+ You can find examples in `smoke` directory.
85
106
 
86
107
  ## Development
87
108
 
@@ -91,5 +112,5 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
91
112
 
92
113
  ## Contributing
93
114
 
94
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/steep.
115
+ Bug reports and pull requests are welcome on GitHub at https://github.com/soutaro/steep.
95
116
 
@@ -93,9 +93,13 @@ ARGV.each do |arg|
93
93
 
94
94
  unless lines.empty?
95
95
  lines.each do |line|
96
- puts Rainbow(" 🤦‍♀️ Unexpected error found: #{line}").red
96
+ if line =~ /:\d+:\d+:/
97
+ puts Rainbow(" 🤦‍♀️ Unexpected error found: #{line}").red
98
+ failed = true
99
+ else
100
+ puts Rainbow(" 🤦 Unexpected error found, but ignored: #{line}").yellow
101
+ end
97
102
  end
98
- failed = true
99
103
  end
100
104
  end
101
105
 
@@ -56,14 +56,14 @@ module Steep
56
56
  opts.on("--fallback-any-is-error") { fallback_any_is_error = true }
57
57
  end.parse!(argv)
58
58
 
59
- unless no_builtin
60
- signature_dirs.unshift Pathname(__dir__).join("../../stdlib").realpath
61
- end
62
-
63
59
  if signature_dirs.empty?
64
60
  signature_dirs << Pathname("sig")
65
61
  end
66
62
 
63
+ unless no_builtin
64
+ signature_dirs.unshift Pathname(__dir__).join("../../stdlib").realpath
65
+ end
66
+
67
67
  source_paths = argv.map {|path| Pathname(path) }
68
68
  if source_paths.empty?
69
69
  source_paths << Pathname(".")
@@ -34,6 +34,10 @@ module Steep
34
34
  end
35
35
  end
36
36
 
37
+ assignability.errors.each do |error|
38
+ error.puts(stdout)
39
+ end
40
+
37
41
  sources = []
38
42
  each_ruby_source do |source|
39
43
  sources << source
@@ -232,14 +232,19 @@ module Steep
232
232
  class Method
233
233
  attr_reader :super_method
234
234
  attr_reader :types
235
+ attr_reader :attributes
235
236
 
236
- def initialize(types:, super_method:)
237
+ def initialize(types:, super_method:, attributes:)
237
238
  @types = types
238
239
  @super_method = super_method
240
+ @attributes = attributes
239
241
  end
240
242
 
241
243
  def ==(other)
242
- other.is_a?(Method) && other.types == types && other.super_method == super_method
244
+ other.is_a?(Method) &&
245
+ other.types == types &&
246
+ other.super_method == super_method &&
247
+ other.attributes == attributes
243
248
  end
244
249
 
245
250
  def closed?
@@ -262,10 +267,12 @@ module Steep
262
267
  end
263
268
 
264
269
  attr_reader :name
270
+ attr_reader :params
265
271
  attr_reader :methods
266
272
 
267
- def initialize(name:, methods:)
273
+ def initialize(name:, params:, methods:)
268
274
  @name = name
275
+ @params = params
269
276
  @methods = methods
270
277
  end
271
278
 
@@ -274,7 +281,7 @@ module Steep
274
281
  end
275
282
 
276
283
  def ==(other)
277
- other.is_a?(self.class) && other.name == name && other.methods == methods
284
+ other.is_a?(self.class) && other.name == name && other.params == params && other.methods == methods
278
285
  end
279
286
  end
280
287
  end
@@ -66,13 +66,17 @@ simple_type: INTERFACE_NAME { result = Types::Name.interface(name: val[0]) }
66
66
  | INTERFACE_NAME LT type_seq GT { result = Types::Name.interface(name: val[0], params: val[2]) }
67
67
  | MODULE_NAME { result = Types::Name.instance(name: val[0])}
68
68
  | MODULE_NAME LT type_seq GT { result = Types::Name.instance(name: val[0], params: val[2]) }
69
- | CLASS_IDENT { result = Types::Name.module(name: val[0]) }
69
+ | CLASS_IDENT constructor { result = Types::Name.module(name: val[0], constructor: val[1]) }
70
70
  | ANY { result = Types::Any.new }
71
71
  | TVAR { result = Types::Var.new(name: val[0]) }
72
72
  | CLASS { result = Types::Class.new }
73
73
  | MODULE { result = Types::Class.new }
74
74
  | INSTANCE { result = Types::Instance.new }
75
75
 
76
+ constructor: { result = nil }
77
+ | CONSTRUCTOR
78
+ | NOCONSTRUCTOR
79
+
76
80
  type: simple_type
77
81
  | union_seq { result = Types::Union.new(types: val[0]) }
78
82
 
@@ -89,6 +93,8 @@ keyword: IDENT
89
93
  | CLASS { result = :class }
90
94
  | MODULE { result = :module }
91
95
  | INSTANCE { result = :instance }
96
+ | BLOCK { result = :block }
97
+ | INCLUDE { result = :include }
92
98
 
93
99
  signatures: { result = [] }
94
100
  | interface signatures { result = [val[0]] + val[1] }
@@ -117,12 +123,15 @@ class_member: instance_method_member { result = val[0] }
117
123
  | include_member { result = val[0] }
118
124
  | extend_member { result = val[0] }
119
125
 
120
- instance_method_member: DEF method_name COLON method_type_union { result = Signature::Members::InstanceMethod.new(name: val[1], types: val[3]) }
121
- class_method_member: DEF SELF DOT method_name COLON method_type_union { result = Signature::Members::ModuleMethod.new(name: val[3], types: val[5]) }
122
- class_instance_method_member: DEF SELFQ DOT method_name COLON method_type_union { result = Signature::Members::ModuleInstanceMethod.new(name: val[3], types: val[5]) }
126
+ instance_method_member: DEF constructor_method method_name COLON method_type_union { result = Signature::Members::InstanceMethod.new(name: val[2], types: val[4], constructor: val[1]) }
127
+ class_method_member: DEF constructor_method SELF DOT method_name COLON method_type_union { result = Signature::Members::ModuleMethod.new(name: val[4], types: val[6], constructor: val[1]) }
128
+ class_instance_method_member: DEF constructor_method SELFQ DOT method_name COLON method_type_union { result = Signature::Members::ModuleInstanceMethod.new(name: val[4], types: val[6], constructor: val[1]) }
123
129
  include_member: INCLUDE type { result = Signature::Members::Include.new(name: val[1]) }
124
130
  extend_member: EXTEND type { result = Signature::Members::Extend.new(name: val[1]) }
125
131
 
132
+ constructor_method: { result = false }
133
+ | LPAREN CONSTRUCTOR RPAREN { result = true }
134
+
126
135
  super_opt: { result = nil }
127
136
  | LTCOLON type { result = val[1] }
128
137
 
@@ -152,6 +161,11 @@ method_name: IDENT
152
161
  | INSTANCE { result = :instance }
153
162
  | OPERATOR
154
163
  | METHOD_NAME
164
+ | BLOCK { result = :block }
165
+ | INCLUDE { result = :include }
166
+ | CONSTRUCTOR { result = :constructor }
167
+ | NOCONSTRUCTOR { result = :noconstructor }
168
+ | GT GT { result = :>> }
155
169
 
156
170
  annotation: AT_TYPE VAR subject COLON type { result = Annotation::VarType.new(var: val[2], type: val[4]) }
157
171
  | AT_TYPE METHOD subject COLON method_type { result = Annotation::MethodType.new(method: val[2], type: val[4]) }
@@ -241,7 +255,7 @@ def next_token
241
255
  [:DOT, nil]
242
256
  when input.scan(/<:/)
243
257
  [:LTCOLON, nil]
244
- when input.scan(/(\[\]=)|(\[\])|===|==|\^|!=|<<|>>/)
258
+ when input.scan(/(\[\]=)|(\[\])|===|==|\^|!=|<</)
245
259
  [:OPERATOR, input.matched.to_sym]
246
260
  when input.scan(/</)
247
261
  [:LT, nil]
@@ -295,6 +309,10 @@ def next_token
295
309
  [:IVAR, nil]
296
310
  when input.scan(/extension\b/)
297
311
  [:EXTENSION, nil]
312
+ when input.scan(/constructor\b/)
313
+ [:CONSTRUCTOR, true]
314
+ when input.scan(/noconstructor\b/)
315
+ [:NOCONSTRUCTOR, false]
298
316
  when input.scan(/[A-Z]\w*\.(class|module)\b/)
299
317
  [:CLASS_IDENT, input.matched.gsub(/\.(class|module)$/, '').to_sym]
300
318
  when input.scan(/\w+(\!|\?)/)
@@ -2,48 +2,70 @@ module Steep
2
2
  module Signature
3
3
  module Members
4
4
  class InstanceMethod
5
+ # @implements Steep__SignatureMember__Method
6
+
7
+ # @dynamic name
5
8
  attr_reader :name
9
+ # @dynamic types
6
10
  attr_reader :types
7
11
 
8
- def initialize(name:, types:)
12
+ attr_reader :constructor
13
+
14
+ def initialize(name:, types:, constructor:)
9
15
  @name = name
10
16
  @types = types
17
+ @constructor = constructor
11
18
  end
12
19
 
13
20
  def ==(other)
14
- other.is_a?(InstanceMethod) && other.name == name && other.types == types
21
+ other.is_a?(self.class) && other.name == name && other.types == types && other.constructor == constructor
15
22
  end
16
23
  end
17
24
 
18
25
  class ModuleMethod
26
+ # @implements Steep__SignatureMember__Method
27
+
28
+ # @dynamic name
19
29
  attr_reader :name
30
+ # @dynamic types
20
31
  attr_reader :types
32
+ attr_reader :constructor
21
33
 
22
- def initialize(name:, types:)
34
+ def initialize(name:, types:, constructor:)
23
35
  @name = name
24
36
  @types = types
37
+ @constructor = constructor
25
38
  end
26
39
 
27
40
  def ==(other)
28
- other.is_a?(ModuleMethod) && other.name == name && other.types == types
41
+ other.is_a?(self.class) && other.name == name && other.types == types && other.constructor == constructor
29
42
  end
30
43
  end
31
44
 
32
45
  class ModuleInstanceMethod
46
+ # @implements Steep__SignatureMember__Method
47
+
48
+ # @dynamic name
33
49
  attr_reader :name
50
+ # @dynamic types
34
51
  attr_reader :types
52
+ attr_reader :constructor
35
53
 
36
- def initialize(name:, types:)
54
+ def initialize(name:, types:, constructor:)
37
55
  @name = name
38
56
  @types = types
57
+ @constructor = constructor
39
58
  end
40
59
 
41
60
  def ==(other)
42
- other.is_a?(ModuleInstanceMethod) && other.name == name && other.types == types
61
+ other.is_a?(self.class) && other.name == name && other.types == types && other.constructor == constructor
43
62
  end
44
63
  end
45
64
 
46
65
  class Include
66
+ # @implements Steep__SignatureMember__Include
67
+
68
+ # @dynamic name
47
69
  attr_reader :name
48
70
 
49
71
  def initialize(name:)
@@ -56,6 +78,9 @@ module Steep
56
78
  end
57
79
 
58
80
  class Extend
81
+ # @implements Steep__SignatureMember__Extend
82
+
83
+ # @dynamic name
59
84
  attr_reader :name
60
85
 
61
86
  def initialize(name:)
@@ -69,6 +94,8 @@ module Steep
69
94
  end
70
95
 
71
96
  module WithMethods
97
+ # @implements Steep__Signature__WithMethods
98
+
72
99
  def instance_methods(assignability:, klass:, instance:, params:)
73
100
  methods = super
74
101
 
@@ -77,19 +104,32 @@ module Steep
77
104
  members.each do |member|
78
105
  case member
79
106
  when Members::Include
80
- module_signature = assignability.lookup_included_signature(member.name)
107
+ # @type var include_member: Steep__SignatureMember__Include
108
+ include_member = member
109
+ module_signature = assignability.lookup_included_signature(include_member.name)
81
110
  merge_methods(methods, module_signature.instance_methods(assignability: assignability,
82
111
  klass: klass,
83
112
  instance: instance,
84
- params: module_signature.type_application_hash(member.name.params)))
113
+ params: module_signature.type_application_hash(include_member.name.params)))
114
+
85
115
  end
86
116
  end
87
117
 
88
118
  members.each do |member|
89
119
  case member
90
120
  when Members::InstanceMethod, Members::ModuleInstanceMethod
91
- method_types = member.types.map {|type| type.substitute(klass: klass, instance: instance, params: hash) }
92
- merge_methods(methods, member.name => Steep::Interface::Method.new(types: method_types, super_method: nil))
121
+ # @type var method_member: Steep__SignatureMember__Method
122
+ method_member = member
123
+ method_types = method_member.types.map {|type| type.substitute(klass: klass, instance: instance, params: hash) }
124
+
125
+ attributes = [].tap do |attrs|
126
+ attrs.push(:constructor) if method_member.constructor
127
+ end
128
+
129
+ merge_methods(methods,
130
+ method_member.name => Steep::Interface::Method.new(types: method_types,
131
+ super_method: nil,
132
+ attributes: attributes))
93
133
  end
94
134
  end
95
135
 
@@ -102,7 +142,7 @@ module Steep
102
142
  methods
103
143
  end
104
144
 
105
- def module_methods(assignability:, klass:, instance:, params:)
145
+ def module_methods(assignability:, klass:, instance:, params:, constructor:)
106
146
  methods = super
107
147
 
108
148
  members.each do |member|
@@ -112,7 +152,8 @@ module Steep
112
152
  merge_methods(methods, module_signature.module_methods(assignability: assignability,
113
153
  klass: klass,
114
154
  instance: instance,
115
- params: module_signature.type_application_hash(member.name.params)))
155
+ params: module_signature.type_application_hash(member.name.params),
156
+ constructor: constructor))
116
157
  when Members::Extend
117
158
  module_signature = assignability.lookup_included_signature(member.name)
118
159
  merge_methods(methods, module_signature.instance_methods(assignability: assignability,
@@ -125,24 +166,30 @@ module Steep
125
166
  members.each do |member|
126
167
  case member
127
168
  when Members::ModuleInstanceMethod, Members::ModuleMethod
128
- method_types = member.types.map {|type| type.substitute(klass: klass, instance: instance, params: {}) }
129
- merge_methods(methods, member.name => Steep::Interface::Method.new(types: method_types, super_method: nil))
169
+ # @type var method_member: Steep__SignatureMember__Method
170
+ method_member = member
171
+ method_types = method_member.types.map {|type| type.substitute(klass: klass, instance: instance, params: {}) }
172
+ merge_methods(methods,
173
+ method_member.name => Steep::Interface::Method.new(types: method_types,
174
+ super_method: nil,
175
+ attributes: []))
130
176
  end
131
177
  end
132
178
 
133
- if self.is_a?(Class)
179
+ if is_class? && constructor
134
180
  instance_methods = instance_methods(assignability: assignability, klass: klass, instance: instance, params: params)
135
181
  new_method = if instance_methods[:initialize]
136
182
  types = instance_methods[:initialize].types.map do |method_type|
137
183
  method_type.updated(return_type: instance)
138
184
  end
139
- Steep::Interface::Method.new(types: types, super_method: nil)
185
+ Steep::Interface::Method.new(types: types, super_method: nil, attributes: [])
140
186
  else
141
187
  Steep::Interface::Method.new(types: [Steep::Interface::MethodType.new(type_params: [],
142
188
  params: Steep::Interface::Params.empty,
143
189
  block: nil,
144
190
  return_type: instance)],
145
- super_method: nil)
191
+ super_method: nil,
192
+ attributes: [])
146
193
  end
147
194
  methods[:new] = new_method
148
195
  end
@@ -152,21 +199,27 @@ module Steep
152
199
 
153
200
  def merge_methods(methods, hash)
154
201
  hash.each_key do |name|
155
- method = hash[name]
202
+ new_method = hash[name]
203
+ old_method = methods[name]
204
+ attributes = (new_method.attributes + (old_method&.attributes || [])).sort.uniq
156
205
 
157
- methods[name] = Steep::Interface::Method.new(types: method.types,
158
- super_method: methods[name])
206
+ methods[name] = Steep::Interface::Method.new(types: new_method.types,
207
+ super_method: old_method,
208
+ attributes: attributes)
159
209
  end
160
210
  end
161
211
  end
162
212
 
163
213
  module WithMembers
214
+ # @implements Steep__Signature__WithMembers
164
215
  def each_type
165
216
  if block_given?
166
217
  members.each do |member|
167
218
  case member
168
219
  when Members::InstanceMethod, Members::ModuleMethod, Members::ModuleInstanceMethod
169
- member.types.each do |method_type|
220
+ # @type var method_member: Steep__SignatureMember__Method
221
+ method_member = member
222
+ method_member.types.each do |method_type|
170
223
  method_type.params.each_type do |type|
171
224
  yield type
172
225
  end
@@ -179,7 +232,9 @@ module Steep
179
232
  end
180
233
  end
181
234
  when Members::Include, Members::Extend
182
- yield member.name
235
+ # @type var mixin_member: _Steep__SignatureMember__Mixin
236
+ mixin_member = member
237
+ yield mixin_member.name
183
238
  else
184
239
  raise "Unknown member: #{member.class.inspect}"
185
240
  end
@@ -210,15 +265,23 @@ module Steep
210
265
  end
211
266
 
212
267
  module WithParams
268
+ # @implements Steep__Signature__WithParams
269
+
213
270
  def type_application_hash(args)
214
271
  Hash[params.zip(args)]
215
272
  end
216
273
  end
217
274
 
218
275
  class Module
276
+ # @implements Steep__Signature__Module
277
+
278
+ # @dynamic name
219
279
  attr_reader :name
280
+ # @dynamic params
220
281
  attr_reader :params
282
+ # @dynamic members
221
283
  attr_reader :members
284
+ # @dynamic self_type
222
285
  attr_reader :self_type
223
286
 
224
287
  prepend WithMethods
@@ -240,7 +303,7 @@ module Steep
240
303
  {}
241
304
  end
242
305
 
243
- def module_methods(assignability:, klass:, instance:, params:)
306
+ def module_methods(assignability:, klass:, instance:, params:, constructor:)
244
307
  {}
245
308
  end
246
309
 
@@ -264,13 +327,28 @@ module Steep
264
327
  params.map {|x| Types::Var.new(name: x) })
265
328
 
266
329
  validate_mixins(assignability, interface)
330
+
331
+ # FIXME: There is no check for initializer compatibility
332
+ if interface.methods.values.any? {|method| method.attributes.include?(:constructor) }
333
+ assignability.errors << Signature::Errors::ConstructorNoCheck.new(signature: self)
334
+ end
335
+ end
336
+
337
+ def is_class?
338
+ false
267
339
  end
268
340
  end
269
341
 
270
342
  class Class
343
+ # @implements Steep__Signature__Class
344
+
345
+ # @dynamic name
271
346
  attr_reader :name
347
+ # @dynamic params
272
348
  attr_reader :params
349
+ # @dynamic members
273
350
  attr_reader :members
351
+ # @dynamic super_class
274
352
  attr_reader :super_class
275
353
 
276
354
  prepend WithMethods
@@ -304,7 +382,7 @@ module Steep
304
382
  end
305
383
  end
306
384
 
307
- def module_methods(assignability:, klass:, instance:, params:)
385
+ def module_methods(assignability:, klass:, instance:, params:, constructor:)
308
386
  signature = assignability.lookup_class_signature(Types::Name.instance(name: :Class))
309
387
  class_methods = signature.instance_methods(assignability: assignability,
310
388
  klass: klass,
@@ -321,7 +399,11 @@ module Steep
321
399
  type.substitute(klass: klass, instance: instance, params: hash)
322
400
  end
323
401
 
324
- class_methods.merge!(signature.module_methods(assignability: assignability, klass: klass, instance: instance, params: super_class_params))
402
+ class_methods.merge!(signature.module_methods(assignability: assignability,
403
+ klass: klass,
404
+ instance: instance,
405
+ params: super_class_params,
406
+ constructor: constructor))
325
407
  end
326
408
  end
327
409
 
@@ -342,7 +424,8 @@ module Steep
342
424
  end
343
425
 
344
426
  interface = assignability.resolve_interface(TypeName::Instance.new(name: name),
345
- params.map {|x| Types::Var.new(name: x) })
427
+ params.map {|x| Types::Var.new(name: x) },
428
+ constructor: true)
346
429
 
347
430
  interface.methods.each_key do |method_name|
348
431
  method = interface.methods[method_name]
@@ -352,6 +435,15 @@ module Steep
352
435
  end
353
436
 
354
437
  validate_mixins(assignability, interface)
438
+
439
+ # FIXME: There is no check for initializer compatibility
440
+ if interface.methods.values.any? {|method| method.attributes.include?(:constructor) }
441
+ assignability.errors << Signature::Errors::ConstructorNoCheck.new(signature: self)
442
+ end
443
+ end
444
+
445
+ def is_class?
446
+ true
355
447
  end
356
448
  end
357
449
  end