steep 0.16.3 → 0.20.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2b1c04c7f20a2ed355b58570363447b3e8f2bd1710407de1e23c7b9fbe279cb8
4
- data.tar.gz: 62101db41144f3fd218ee8478ab377f3414ad1d8a7689ac73356aa28bf7f6842
3
+ metadata.gz: 566e77aa4db03cb06ae80569f4db9f5409e65199b1af4af9fc6f2598e911f694
4
+ data.tar.gz: 41f1d54c5196fdec7cc58751899aec208066d845eef717234bb37266313c7d8d
5
5
  SHA512:
6
- metadata.gz: d8ac130b1adb7755709f4b1590939b442d6d4b4aa5ea38a95423db539a1b52b0c4078abf1a543b92a84477d99846d5ab30060dc26c693f52785de0c205041a2d
7
- data.tar.gz: e7ccec14707e49d51b88429ab0922c4e6fbbc190bbafb0e107c30ea681b04415245e40708909fd28458a89a565a816fd88a6bfa1c14b76e24185a2ece153148c
6
+ metadata.gz: 46366ed11a6328a6a237c52042ef49eb12d5ce3db111fb55c5038109b62aa471ba6634c8c060575f6862658dcc0f388684a083f9a691becd6d90f076acb05908
7
+ data.tar.gz: 9cb15861e6de6b5209dd82745f1c7cf67c212e3e15cc9c1f92956b84089801f994c7c1cd79ff8972f37da229530e7354d237ce4a74ce844083daf656936286dc
@@ -14,6 +14,10 @@ jobs:
14
14
  container_tag:
15
15
  - 2.6.5-bionic
16
16
  - 2.7.0-bionic
17
+ task:
18
+ - test
19
+ - smoke
20
+ - build
17
21
  container:
18
22
  image: rubylang/ruby:${{ matrix.container_tag }}
19
23
  steps:
@@ -24,4 +28,4 @@ jobs:
24
28
  gem install bundler
25
29
  bundle install --jobs 4 --retry 3
26
30
  bin/setup
27
- bundle exec rake build test smoke
31
+ bundle exec rake ${{matrix.task}}
@@ -2,6 +2,30 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 0.20.0 (2020-07-17)
6
+
7
+ * Support singleton class definitions ([#166](https://github.com/soutaro/steep/pull/166))
8
+
9
+ ## 0.19.0 (2020-07-12)
10
+
11
+ * Update RBS. ([#157](https://github.com/soutaro/steep/pull/157))
12
+ * No `initialize` in completion. ([#164](https://github.com/soutaro/steep/pull/164))
13
+ * Granular typing option setup. ([#163](https://github.com/soutaro/steep/pull/163))
14
+
15
+ ## 0.18.0 (2020-07-06)
16
+
17
+ * Sort result of `Pathname#glob` ([#154](https://github.com/soutaro/steep/pull/154))
18
+ * Sort methods in LanguageServer to return non-inherited methods first ([#159](https://github.com/soutaro/steep/pull/159))
19
+
20
+ ## 0.17.1 (2020-06-15)
21
+
22
+ * Allow RBS gem to be 0.4 ([#153](https://github.com/soutaro/steep/pull/153))
23
+
24
+ ## 0.17.0 (2020-06-13)
25
+
26
+ * Fix `steep watch` and `steep langserver` to correctly handle error message filterings based on options ([#152](https://github.com/soutaro/steep/pull/152))
27
+ * Fix typing of collections ([#151](https://github.com/soutaro/steep/pull/151))
28
+
5
29
  ## 0.16.3
6
30
 
7
31
  * Fix `steep watch` ([#147](https://github.com/soutaro/steep/pull/147))
@@ -12,6 +12,7 @@ require 'language_server-protocol'
12
12
  require "etc"
13
13
  require "open3"
14
14
  require "stringio"
15
+ require 'uri'
15
16
 
16
17
  require "rbs"
17
18
 
@@ -8,6 +8,10 @@ module Steep
8
8
  @definition_builder = builder
9
9
  end
10
10
 
11
+ def type_name_resolver
12
+ @type_name_resolver ||= RBS::TypeNameResolver.from_env(definition_builder.env)
13
+ end
14
+
11
15
  def type(type)
12
16
  case type
13
17
  when RBS::Types::Bases::Any
@@ -277,8 +281,7 @@ module Steep
277
281
 
278
282
  def unfold(type_name)
279
283
  type_name_1(type_name).yield_self do |type_name|
280
- decl = definition_builder.env.find_alias(type_name) or raise "Unknown type name: #{type_name}"
281
- type(definition_builder.env.absolute_type(decl.type, namespace: type_name.namespace))
284
+ type(definition_builder.expand_alias(type_name))
282
285
  end
283
286
  end
284
287
 
@@ -331,7 +334,7 @@ module Steep
331
334
  method.method_types.map do |type|
332
335
  method_type(type, self_type: self_type) {|ty| ty.subst(subst) }
333
336
  end,
334
- incompatible: method.attributes.include?(:incompatible)
337
+ incompatible: name == :initialize || name == :new
335
338
  )
336
339
  end
337
340
  end
@@ -339,8 +342,7 @@ module Steep
339
342
  when Name::Interface
340
343
  Interface::Interface.new(type: self_type, private: private).tap do |interface|
341
344
  type_name = type_name_1(type.name)
342
- decl = definition_builder.env.find_class(type_name) or raise "Unknown class: #{type_name}"
343
- definition = definition_builder.build_interface(type_name, decl)
345
+ definition = definition_builder.build_interface(type_name)
344
346
 
345
347
  subst = Interface::Substitution.build(
346
348
  definition.type_params,
@@ -363,7 +365,7 @@ module Steep
363
365
  definition = definition_builder.build_singleton(type_name_1(type.name))
364
366
 
365
367
  instance_type = Name::Instance.new(name: type.name,
366
- args: definition.declaration.type_params.each.map {Any.new(location: nil)},
368
+ args: definition.type_params.map {Any.new(location: nil)},
367
369
  location: nil)
368
370
  subst = Interface::Substitution.build(
369
371
  [],
@@ -543,12 +545,12 @@ module Steep
543
545
 
544
546
  def module_name?(type_name)
545
547
  name = type_name_1(type_name)
546
- env.class?(name) && env.find_class(name).is_a?(RBS::AST::Declarations::Module)
548
+ entry = env.class_decls[name] and entry.is_a?(RBS::Environment::ModuleEntry)
547
549
  end
548
550
 
549
551
  def class_name?(type_name)
550
552
  name = type_name_1(type_name)
551
- env.class?(name) && env.find_class(name).is_a?(RBS::AST::Declarations::Class)
553
+ entry = env.class_decls[name] and entry.is_a?(RBS::Environment::ClassEntry)
552
554
  end
553
555
 
554
556
  def env
@@ -556,13 +558,14 @@ module Steep
556
558
  end
557
559
 
558
560
  def absolute_type(type, namespace:)
559
- type(env.absolute_type(type_1(type),
560
- namespace: namespace_1(namespace)) {|type| type.name.absolute! })
561
+ absolute_type = type_1(type).map_type_name do |name|
562
+ absolute_type_name(name, namespace: namespace) || name.absolute!
563
+ end
564
+ type(absolute_type)
561
565
  end
562
566
 
563
567
  def absolute_type_name(type_name, namespace:)
564
- type(env.absolute_type_name(type_name_1(type_name),
565
- namespace: namespace_1(namespace)) {|name| name.absolute! })
568
+ type_name_resolver.resolve(type_name, context: namespace_1(namespace).ascend)
566
569
  end
567
570
  end
568
571
  end
@@ -53,18 +53,7 @@ module Steep
53
53
  status.type_check_sources.each do |source_file|
54
54
  case source_file.status
55
55
  when Project::SourceFile::TypeCheckStatus
56
- source_file.errors.reject do |error|
57
- case
58
- when error.is_a?(Errors::FallbackAny)
59
- target.options.allow_fallback_any
60
- when error.is_a?(Errors::MethodDefinitionMissing)
61
- target.options.allow_missing_definitions
62
- when error.is_a?(Errors::NoMethod)
63
- target.options.allow_unknown_method_calls
64
- when error.is_a?(Errors::UnknownConstantAssigned)
65
- target.options.allow_unknown_constant_assignment
66
- end
67
- end.each do |error|
56
+ source_file.errors.select {|error| target.options.error_to_report?(error) }.each do |error|
68
57
  error.print_to stdout
69
58
  end
70
59
  when Project::SourceFile::TypeCheckErrorStatus
@@ -10,7 +10,15 @@ module Steep
10
10
 
11
11
  InstanceVariableItem = Struct.new(:identifier, :range, :type, keyword_init: true)
12
12
  LocalVariableItem = Struct.new(:identifier, :range, :type, keyword_init: true)
13
- MethodNameItem = Struct.new(:identifier, :range, :definition, :method_type, keyword_init: true)
13
+ MethodNameItem = Struct.new(:identifier, :range, :definition, :def_type, :inherited_method, keyword_init: true) do
14
+ def method_type
15
+ def_type.type
16
+ end
17
+
18
+ def comment
19
+ def_type.comment
20
+ end
21
+ end
14
22
 
15
23
  attr_reader :source_text
16
24
  attr_reader :path
@@ -231,20 +239,22 @@ module Steep
231
239
  subtyping.factory.definition_builder.build_singleton(type_name)
232
240
  when AST::Types::Name::Interface
233
241
  type_name = subtyping.factory.type_name_1(type.name)
234
- interface = subtyping.factory.env.find_class(type_name)
235
- subtyping.factory.definition_builder.build_interface(type_name, interface)
242
+ subtyping.factory.definition_builder.build_interface(type_name)
236
243
  end
237
244
 
238
245
  if definition
239
246
  definition.methods.each do |name, method|
247
+ next if disallowed_method?(name)
248
+
240
249
  if include_private || method.public?
241
250
  if name.to_s.start_with?(prefix)
242
251
  if word_name?(name.to_s)
243
- method.method_types.each do |method_type|
252
+ method.defs.each do |def_type|
244
253
  items << MethodNameItem.new(identifier: name,
245
254
  range: range,
246
255
  definition: method,
247
- method_type: method_type)
256
+ def_type: def_type,
257
+ inherited_method: inherited_method?(method, definition))
248
258
  end
249
259
  end
250
260
  end
@@ -293,6 +303,17 @@ module Steep
293
303
 
294
304
  index
295
305
  end
306
+
307
+ def inherited_method?(method, definition)
308
+ method.implemented_in != definition.type_name
309
+ end
310
+
311
+ def disallowed_method?(name)
312
+ # initialize isn't invoked by developers when creating
313
+ # instances of new classes, so don't show it as
314
+ # an LSP option
315
+ name == :initialize
316
+ end
296
317
  end
297
318
  end
298
319
  end
@@ -10,6 +10,7 @@ module Steep
10
10
  attr_reader :no_builtin
11
11
  attr_reader :vendor_dir
12
12
  attr_reader :strictness_level
13
+ attr_reader :typing_option_hash
13
14
 
14
15
  def initialize(name, sources: [], libraries: [], signatures: [], ignored_sources: [])
15
16
  @name = name
@@ -19,6 +20,7 @@ module Steep
19
20
  @ignored_sources = ignored_sources
20
21
  @vendor_dir = nil
21
22
  @strictness_level = :default
23
+ @typing_option_hash = {}
22
24
  end
23
25
 
24
26
  def initialize_copy(other)
@@ -29,6 +31,7 @@ module Steep
29
31
  @ignored_sources = other.ignored_sources.dup
30
32
  @vendor_dir = other.vendor_dir
31
33
  @strictness_level = other.strictness_level
34
+ @typing_option_hash = other.typing_option_hash
32
35
  end
33
36
 
34
37
  def check(*args)
@@ -43,8 +46,9 @@ module Steep
43
46
  libraries.push(*args)
44
47
  end
45
48
 
46
- def typing_options(level)
49
+ def typing_options(level = @strictness_level, **hash)
47
50
  @strictness_level = level
51
+ @typing_option_hash = hash
48
52
  end
49
53
 
50
54
  def signature(*args)
@@ -128,6 +132,8 @@ module Steep
128
132
  options.apply_lenient_typing_options!
129
133
  end
130
134
 
135
+ options.merge!(target.typing_option_hash)
136
+
131
137
  case target.vendor_dir
132
138
  when Array
133
139
  options.vendored_stdlib_path = target.vendor_dir[0]
@@ -95,6 +95,13 @@ module Steep
95
95
  source: source,
96
96
  timestamp: Time.now
97
97
  )
98
+ rescue RBS::NoTypeFoundError,
99
+ RBS::NoMixinFoundError,
100
+ RBS::NoSuperclassFoundError,
101
+ RBS::DuplicatedMethodDefinitionError,
102
+ RBS::InvalidTypeApplicationError => exn
103
+ # Skip logging known signature errors (they are handled with load_signatures(validate: true))
104
+ @status = TypeCheckErrorStatus.new(error: exn)
98
105
  rescue => exn
99
106
  Steep.log_error(exn)
100
107
  @status = TypeCheckErrorStatus.new(error: exn)
@@ -20,7 +20,7 @@ module Steep
20
20
  Pathname.glob(absolute_path)
21
21
  end
22
22
 
23
- files.each do |source_path|
23
+ files.sort.each do |source_path|
24
24
  yield project.relative_path(source_path)
25
25
  end
26
26
  end
@@ -4,7 +4,13 @@ module Steep
4
4
  TypeContent = Struct.new(:node, :type, :location, keyword_init: true)
5
5
  VariableContent = Struct.new(:node, :name, :type, :location, keyword_init: true)
6
6
  MethodCallContent = Struct.new(:node, :method_name, :type, :definition, :location, keyword_init: true)
7
- DefinitionContent = Struct.new(:node, :method_name, :method_type, :definition, :location, keyword_init: true)
7
+ DefinitionContent = Struct.new(:node, :method_name, :method_type, :definition, :location, keyword_init: true) do
8
+ def comment_string
9
+ if comments = definition&.comments
10
+ comments.map {|c| c.string.chomp }.uniq.join("\n----\n")
11
+ end
12
+ end
13
+ end
8
14
 
9
15
  InstanceMethodName = Struct.new(:class_name, :method_name)
10
16
  SingletonMethodName = Struct.new(:class_name, :method_name)
@@ -80,7 +86,7 @@ module Steep
80
86
  when AST::Types::Name::Instance
81
87
  method_definition = method_definition_for(factory, receiver_type.name, instance_method: method_name)
82
88
  if method_definition&.defined_in
83
- owner_name = factory.type_name(method_definition.defined_in.name.absolute!)
89
+ owner_name = factory.type_name(method_definition.defined_in)
84
90
  [
85
91
  InstanceMethodName.new(owner_name, method_name),
86
92
  method_definition
@@ -89,7 +95,7 @@ module Steep
89
95
  when AST::Types::Name::Class
90
96
  method_definition = method_definition_for(factory, receiver_type.name, singleton_method: method_name)
91
97
  if method_definition&.defined_in
92
- owner_name = factory.type_name(method_definition.defined_in.name.absolute!)
98
+ owner_name = factory.type_name(method_definition.defined_in)
93
99
  [
94
100
  SingletonMethodName.new(owner_name, method_name),
95
101
  method_definition
@@ -37,6 +37,28 @@ module Steep
37
37
  self.allow_unknown_constant_assignment = true
38
38
  self.allow_unknown_method_calls = true
39
39
  end
40
+
41
+ def error_to_report?(error)
42
+ case
43
+ when error.is_a?(Errors::FallbackAny)
44
+ !allow_fallback_any
45
+ when error.is_a?(Errors::MethodDefinitionMissing)
46
+ !allow_missing_definitions
47
+ when error.is_a?(Errors::NoMethod)
48
+ !allow_unknown_method_calls
49
+ when error.is_a?(Errors::UnknownConstantAssigned)
50
+ !allow_unknown_constant_assignment
51
+ else
52
+ true
53
+ end
54
+ end
55
+
56
+ def merge!(hash)
57
+ self.allow_fallback_any = hash[:allow_fallback_any] if hash.key?(:allow_fallback_any)
58
+ self.allow_missing_definitions = hash[:allow_missing_definitions] if hash.key?(:allow_missing_definitions)
59
+ self.allow_unknown_constant_assignment = hash[:allow_unknown_constant_assignment] if hash.key?(:allow_unknown_constant_assignment)
60
+ self.allow_unknown_method_calls = hash[:allow_unknown_method_calls] if hash.key?(:allow_unknown_method_calls)
61
+ end
40
62
  end
41
63
  end
42
64
  end
@@ -15,6 +15,7 @@ module Steep
15
15
 
16
16
  SignatureSyntaxErrorStatus = Struct.new(:timestamp, :errors, keyword_init: true)
17
17
  SignatureValidationErrorStatus = Struct.new(:timestamp, :errors, keyword_init: true)
18
+ SignatureOtherErrorStatus = Struct.new(:timestamp, :error, keyword_init: true)
18
19
  TypeCheckStatus = Struct.new(:environment, :subtyping, :type_check_sources, :timestamp, keyword_init: true)
19
20
 
20
21
  def initialize(name:, options:, source_patterns:, ignore_patterns:, signature_patterns:)
@@ -95,7 +96,7 @@ module Steep
95
96
  end
96
97
 
97
98
  def environment
98
- @environment ||= RBS::Environment.new().tap do |env|
99
+ @environment ||= RBS::Environment.new().yield_self do |env|
99
100
  stdlib_root = options.vendored_stdlib_path || RBS::EnvironmentLoader::STDLIB_ROOT
100
101
  gem_vendor_path = options.vendored_gems_path
101
102
  loader = RBS::EnvironmentLoader.new(stdlib_root: stdlib_root, gem_vendor_path: gem_vendor_path)
@@ -103,6 +104,8 @@ module Steep
103
104
  loader.add(library: lib)
104
105
  end
105
106
  loader.load(env: env)
107
+
108
+ env.resolve_type_names
106
109
  end
107
110
  end
108
111
 
@@ -125,34 +128,40 @@ module Steep
125
128
  if status.is_a?(TypeCheckStatus) && updated_files.empty?
126
129
  yield status.environment, status.subtyping, status.timestamp
127
130
  else
128
- env = environment.dup
129
-
130
- signature_files.each_value do |file|
131
- if file.status.is_a?(SignatureFile::DeclarationsStatus)
132
- file.status.declarations.each do |decl|
133
- env << decl
131
+ begin
132
+ env = environment.dup
133
+
134
+ signature_files.each_value do |file|
135
+ if file.status.is_a?(SignatureFile::DeclarationsStatus)
136
+ file.status.declarations.each do |decl|
137
+ env << decl
138
+ end
134
139
  end
135
140
  end
136
- end
137
141
 
138
- definition_builder = RBS::DefinitionBuilder.new(env: env)
139
- factory = AST::Types::Factory.new(builder: definition_builder)
140
- check = Subtyping::Check.new(factory: factory)
142
+ env = env.resolve_type_names
141
143
 
142
- if validate
143
- validator = Signature::Validator.new(checker: check)
144
- validator.validate()
144
+ definition_builder = RBS::DefinitionBuilder.new(env: env)
145
+ factory = AST::Types::Factory.new(builder: definition_builder)
146
+ check = Subtyping::Check.new(factory: factory)
145
147
 
146
- if validator.no_error?
147
- yield env, check, Time.now
148
+ if validate
149
+ validator = Signature::Validator.new(checker: check)
150
+ validator.validate()
151
+
152
+ if validator.no_error?
153
+ yield env, check, Time.now
154
+ else
155
+ @status = SignatureValidationErrorStatus.new(
156
+ errors: validator.each_error.to_a,
157
+ timestamp: Time.now
158
+ )
159
+ end
148
160
  else
149
- @status = SignatureValidationErrorStatus.new(
150
- errors: validator.each_error.to_a,
151
- timestamp: Time.now
152
- )
161
+ yield env, check, Time.now
153
162
  end
154
- else
155
- yield env, check, Time.now
163
+ rescue => exn
164
+ @status = SignatureOtherErrorStatus.new(error: exn, timestamp: Time.now)
156
165
  end
157
166
  end
158
167
 
@@ -47,7 +47,7 @@ module Steep
47
47
 
48
48
  Steep.logger.info "Finished type checking: #{path}@#{target.name}"
49
49
 
50
- diagnostics = source_diagnostics(source)
50
+ diagnostics = source_diagnostics(source, target.options)
51
51
 
52
52
  writer.write(
53
53
  method: :"textDocument/publishDiagnostics",
@@ -58,7 +58,7 @@ module Steep
58
58
  )
59
59
  end
60
60
 
61
- def source_diagnostics(source)
61
+ def source_diagnostics(source, options)
62
62
  case status = source.status
63
63
  when Project::SourceFile::ParseErrorStatus
64
64
  []
@@ -80,7 +80,7 @@ module Steep
80
80
  )
81
81
  ]
82
82
  when Project::SourceFile::TypeCheckStatus
83
- status.typing.errors.map do |error|
83
+ status.typing.errors.select {|error| options.error_to_report?(error) }.map do |error|
84
84
  loc = error.location_to_str
85
85
 
86
86
  LSP::Interface::Diagnostic.new(
@@ -110,7 +110,7 @@ HOVER
110
110
  def #{content.method_name}: #{content.method_type}
111
111
  ```
112
112
  HOVER
113
- if (comment = content.definition.comment)
113
+ if (comment = content.comment_string)
114
114
  string << "\n----\n\n#{comment.string}\n"
115
115
  end
116
116
 
@@ -190,8 +190,9 @@ HOVER
190
190
  new_text: "#{item.identifier}#{method_type_snippet}",
191
191
  range: range
192
192
  ),
193
- documentation: item.definition.comment&.string,
194
- insert_text_format: LanguageServer::Protocol::Constant::InsertTextFormat::SNIPPET
193
+ documentation: item.comment&.string,
194
+ insert_text_format: LanguageServer::Protocol::Constant::InsertTextFormat::SNIPPET,
195
+ sort_text: item.inherited_method ? 'z' : 'a' # Ensure language server puts non-inherited methods before inherited methods
195
196
  )
196
197
  when Project::CompletionProvider::InstanceVariableItem
197
198
  label = "#{item.identifier}: #{item.type}"
@@ -114,6 +114,7 @@ module Steep
114
114
  end
115
115
  else
116
116
  Steep.logger.info "Unexpected target status: #{status.class}"
117
+ {}
117
118
  end
118
119
 
119
120
  diagnostics.each do |path, diags|
@@ -35,6 +35,14 @@ module Steep
35
35
  checker.factory.definition_builder
36
36
  end
37
37
 
38
+ def type_name_resolver
39
+ @type_name_resolver ||= RBS::TypeNameResolver.from_env(env)
40
+ end
41
+
42
+ def validator
43
+ @validator ||= RBS::Validator.new(env: env, resolver: type_name_resolver)
44
+ end
45
+
38
46
  def factory
39
47
  checker.factory
40
48
  end
@@ -47,57 +55,69 @@ module Steep
47
55
  validate_global
48
56
  end
49
57
 
50
- def validate_one_decl(name, decl)
51
- case decl
52
- when Declarations::Class
53
- rescue_validation_errors do
54
- Steep.logger.debug "#{Location.to_string decl.location}:\tValidating class definition `#{name}`..."
55
- builder.build_instance(decl.name.absolute!).each_type do |type|
56
- env.validate type, namespace: RBS::Namespace.root
58
+ def validate_type(type)
59
+ Steep.logger.debug "#{Location.to_string type.location}: Validating #{type}..."
60
+ validator.validate_type type, context: [RBS::Namespace.root]
61
+ end
62
+
63
+ def validate_one_class(name)
64
+ rescue_validation_errors do
65
+ Steep.logger.debug "Validating class definition `#{name}`..."
66
+ Steep.logger.tagged "#{name}" do
67
+ builder.build_instance(name).each_type do |type|
68
+ validate_type type
57
69
  end
58
- builder.build_singleton(decl.name.absolute!).each_type do |type|
59
- env.validate type, namespace: RBS::Namespace.root
70
+ builder.build_singleton(name).each_type do |type|
71
+ validate_type type
60
72
  end
61
73
  end
62
- when Declarations::Interface
63
- rescue_validation_errors do
64
- Steep.logger.debug "#{Location.to_string decl.location}:\tValidating interface `#{name}`..."
65
- builder.build_interface(decl.name.absolute!, decl).each_type do |type|
66
- env.validate type, namespace: RBS::Namespace.root
74
+ end
75
+ end
76
+
77
+ def validate_one_interface(name)
78
+ rescue_validation_errors do
79
+ Steep.logger.debug "Validating interface `#{name}`..."
80
+ Steep.logger.tagged "#{name}" do
81
+ builder.build_interface(name).each_type do |type|
82
+ validate_type type
67
83
  end
68
84
  end
69
85
  end
70
86
  end
71
87
 
72
88
  def validate_decl
73
- env.each_decl do |name, decl|
74
- validate_one_decl name, decl
89
+ env.class_decls.each_key do |name|
90
+ validate_one_class(name)
91
+ end
92
+
93
+ env.interface_decls.each_key do |name|
94
+ validate_one_interface(name)
75
95
  end
76
96
  end
77
97
 
78
98
  def validate_const
79
- env.each_constant do |name, decl|
99
+ env.constant_decls.each do |name, entry|
80
100
  rescue_validation_errors do
81
- Steep.logger.debug "#{Location.to_string decl.location}:\tValidating constant `#{name}`..."
82
- env.validate(decl.type, namespace: name.namespace)
101
+ Steep.logger.debug "Validating constant `#{name}`..."
102
+ validate_type entry.decl.type
83
103
  end
84
104
  end
85
105
  end
86
106
 
87
107
  def validate_global
88
- env.each_global do |name, decl|
108
+ env.global_decls.each do |name, entry|
89
109
  rescue_validation_errors do
90
- Steep.logger.debug "#{Location.to_string decl.location}:\tValidating global `#{name}`..."
91
- env.validate(decl.type, namespace: RBS::Namespace.root)
110
+ Steep.logger.debug "Validating global `#{name}`..."
111
+ validate_type entry.decl.type
92
112
  end
93
113
  end
94
114
  end
95
115
 
96
116
  def validate_alias
97
- env.each_alias do |name, decl|
117
+ env.alias_decls.each do |name, entry|
98
118
  rescue_validation_errors do
99
- Steep.logger.debug "#{Location.to_string decl.location}:\tValidating alias `#{name}`..."
100
- env.validate(decl.type, namespace: name.namespace)
119
+ Steep.logger.debug "Validating alias `#{name}`..."
120
+ validate_type(entry.decl.type)
101
121
  end
102
122
  end
103
123
  end
@@ -108,10 +128,10 @@ module Steep
108
128
  @errors << Errors::InvalidTypeApplicationError.new(
109
129
  name: factory.type_name(exn.type_name),
110
130
  args: exn.args.map {|ty| factory.type(ty) },
111
- params: exn.params.each.map(&:name),
131
+ params: exn.params,
112
132
  location: exn.location
113
133
  )
114
- rescue RBS::NoTypeFoundError => exn
134
+ rescue RBS::NoTypeFoundError, RBS::NoSuperclassFoundError, RBS::NoMixinFoundError => exn
115
135
  @errors << Errors::UnknownTypeNameError.new(
116
136
  name: factory.type_name(exn.type_name),
117
137
  location: exn.location
@@ -37,7 +37,6 @@ module Steep
37
37
  attr_reader :source
38
38
  attr_reader :annotations
39
39
  attr_reader :typing
40
- attr_reader :type_env
41
40
 
42
41
  attr_reader :context
43
42
 
@@ -169,7 +168,7 @@ module Steep
169
168
 
170
169
  super_method = if definition
171
170
  if (this_method = definition.methods[method_name])
172
- if module_context&.class_name == checker.factory.type_name(this_method.defined_in.name.absolute!)
171
+ if module_context&.class_name == checker.factory.type_name(this_method.defined_in)
173
172
  this_method.super_method
174
173
  else
175
174
  this_method
@@ -231,6 +230,39 @@ module Steep
231
230
  )
232
231
  end
233
232
 
233
+ def implement_module(module_name:, super_name: nil, annotations:)
234
+ if (annotation = annotations.implement_module_annotation)
235
+ absolute_name(annotation.name.name).yield_self do |absolute_name|
236
+ if checker.factory.class_name?(absolute_name) || checker.factory.module_name?(absolute_name)
237
+ AST::Annotation::Implements::Module.new(
238
+ name: absolute_name,
239
+ args: annotation.name.args
240
+ )
241
+ else
242
+ Steep.logger.error "Unknown class name given to @implements: #{annotation.name.name}"
243
+ nil
244
+ end
245
+ end
246
+ else
247
+ name = nil
248
+ name ||= absolute_name(module_name).yield_self do |absolute_name|
249
+ absolute_name if checker.factory.class_name?(absolute_name) || checker.factory.module_name?(absolute_name)
250
+ end
251
+ name ||= super_name && absolute_name(super_name).yield_self do |absolute_name|
252
+ absolute_name if checker.factory.class_name?(absolute_name) || checker.factory.module_name?(absolute_name)
253
+ end
254
+
255
+ if name
256
+ absolute_name_ = checker.factory.type_name_1(name)
257
+ entry = checker.factory.env.class_decls[absolute_name_]
258
+ AST::Annotation::Implements::Module.new(
259
+ name: name,
260
+ args: entry.type_params.each.map(&:name)
261
+ )
262
+ end
263
+ end
264
+ end
265
+
234
266
  def for_module(node)
235
267
  new_module_name = Names::Module.from_node(node.children.first) or raise "Unexpected module name: #{node.children.first}"
236
268
  new_namespace = nested_namespace_for_module(new_module_name)
@@ -241,35 +273,14 @@ module Steep
241
273
  annots = source.annotations(block: node, factory: checker.factory, current_module: new_namespace)
242
274
  module_type = AST::Builtin::Module.instance_type
243
275
 
244
- implement_module_name = yield_self do
245
- if (annotation = annots.implement_module_annotation)
246
- absolute_name(annotation.name.name).yield_self do |absolute_name|
247
- if checker.factory.module_name?(absolute_name)
248
- AST::Annotation::Implements::Module.new(name: absolute_name,
249
- args: annotation.name.args)
250
- else
251
- Steep.logger.error "Unknown module name given to @implements: #{annotation.name.name}"
252
- nil
253
- end
254
- end
255
- else
256
- absolute_name(new_module_name).yield_self do |absolute_name|
257
- if checker.factory.module_name?(absolute_name)
258
- absolute_name_ = checker.factory.type_name_1(absolute_name)
259
- decl = checker.factory.env.find_class(absolute_name_)
260
- AST::Annotation::Implements::Module.new(name: absolute_name,
261
- args: decl.type_params.each.map(&:name))
262
- end
263
- end
264
- end
265
- end
276
+ implement_module_name = implement_module(module_name: new_module_name, annotations: annots)
266
277
 
267
278
  if implement_module_name
268
279
  module_name = implement_module_name.name
269
280
  module_args = implement_module_name.args.map {|x| AST::Types::Var.new(name: x)}
270
281
 
271
282
  type_name_ = checker.factory.type_name_1(implement_module_name.name)
272
- module_decl = checker.factory.definition_builder.env.find_class(type_name_)
283
+ module_entry = checker.factory.definition_builder.env.class_decls[type_name_]
273
284
  instance_def = checker.factory.definition_builder.build_instance(type_name_)
274
285
  module_def = checker.factory.definition_builder.build_singleton(type_name_)
275
286
 
@@ -277,9 +288,22 @@ module Steep
277
288
  types: [
278
289
  AST::Types::Name::Instance.new(name: module_name, args: module_args),
279
290
  AST::Builtin::Object.instance_type,
280
- module_decl.self_type&.yield_self {|ty|
281
- absolute_type = checker.factory.env.absolute_type(ty, namespace: module_decl.name.absolute!.namespace)
282
- checker.factory.type(absolute_type)
291
+ *module_entry.self_types.map {|module_self|
292
+ type = case
293
+ when module_self.name.interface?
294
+ RBS::Types::Interface.new(
295
+ name: module_self.name,
296
+ args: module_self.args,
297
+ location: module_self.location
298
+ )
299
+ when module_self.name.class?
300
+ RBS::Types::ClassInstance.new(
301
+ name: module_self.name,
302
+ args: module_self.args,
303
+ location: module_self.location
304
+ )
305
+ end
306
+ checker.factory.type(type)
283
307
  }
284
308
  ].compact
285
309
  )
@@ -340,34 +364,7 @@ module Steep
340
364
 
341
365
  annots = source.annotations(block: node, factory: checker.factory, current_module: new_namespace)
342
366
 
343
- implement_module_name = yield_self do
344
- if (annotation = annots.implement_module_annotation)
345
- absolute_name(annotation.name.name).yield_self do |absolute_name|
346
- if checker.factory.class_name?(absolute_name)
347
- AST::Annotation::Implements::Module.new(name: absolute_name,
348
- args: annotation.name.args)
349
- else
350
- Steep.logger.error "Unknown class name given to @implements: #{annotation.name.name}"
351
- nil
352
- end
353
- end
354
- else
355
- name = nil
356
- name ||= absolute_name(new_class_name).yield_self do |absolute_name|
357
- absolute_name if checker.factory.class_name?(absolute_name)
358
- end
359
- name ||= super_class_name && absolute_name(super_class_name).yield_self do |absolute_name|
360
- absolute_name if checker.factory.class_name?(absolute_name)
361
- end
362
-
363
- if name
364
- absolute_name_ = checker.factory.type_name_1(name)
365
- decl = checker.factory.env.find_class(absolute_name_)
366
- AST::Annotation::Implements::Module.new(name: name,
367
- args: decl.type_params.each.map(&:name))
368
- end
369
- end
370
- end
367
+ implement_module_name = implement_module(module_name: new_class_name, super_name: super_class_name, annotations: annots)
371
368
 
372
369
  if annots.implement_module_annotation
373
370
  new_class_name = implement_module_name.name
@@ -436,6 +433,83 @@ module Steep
436
433
  )
437
434
  end
438
435
 
436
+ def for_sclass(node, type)
437
+ annots = source.annotations(block: node, factory: checker.factory, current_module: current_namespace)
438
+
439
+ instance_type = if type.is_a?(AST::Types::Self)
440
+ context.self_type
441
+ else
442
+ type
443
+ end
444
+
445
+ module_type = case instance_type
446
+ when AST::Types::Name::Class
447
+ AST::Builtin::Class.instance_type
448
+ when AST::Types::Name::Module
449
+ AST::Builtin::Module.instance_type
450
+ when AST::Types::Name::Instance
451
+ instance_type.to_class(constructor: nil)
452
+ else
453
+ raise "Unexpected type for sclass node: #{type}"
454
+ end
455
+
456
+ instance_definition = case instance_type
457
+ when AST::Types::Name::Class, AST::Types::Name::Module
458
+ type_name = checker.factory.type_name_1(instance_type.name)
459
+ checker.factory.definition_builder.build_singleton(type_name)
460
+ when AST::Types::Name::Instance
461
+ type_name = checker.factory.type_name_1(instance_type.name)
462
+ checker.factory.definition_builder.build_instance(type_name)
463
+ end
464
+
465
+ module_definition = case module_type
466
+ when AST::Types::Name::Class, AST::Types::Name::Module
467
+ type_name = checker.factory.type_name_1(instance_type.name)
468
+ checker.factory.definition_builder.build_singleton(type_name)
469
+ else
470
+ nil
471
+ end
472
+
473
+ module_context = TypeInference::Context::ModuleContext.new(
474
+ instance_type: annots.instance_type || instance_type,
475
+ module_type: annots.self_type || annots.module_type || module_type,
476
+ implement_name: nil,
477
+ current_namespace: current_namespace,
478
+ const_env: self.module_context.const_env,
479
+ class_name: self.module_context.class_name,
480
+ module_definition: module_definition,
481
+ instance_definition: instance_definition
482
+ )
483
+
484
+ type_env = TypeInference::TypeEnv.build(annotations: annots,
485
+ subtyping: checker,
486
+ const_env: self.module_context.const_env,
487
+ signatures: checker.factory.env)
488
+
489
+ lvar_env = TypeInference::LocalVariableTypeEnv.empty(
490
+ subtyping: checker,
491
+ self_type: module_context.module_type
492
+ ).annotate(annots)
493
+
494
+ body_context = TypeInference::Context.new(
495
+ method_context: nil,
496
+ block_context: nil,
497
+ module_context: module_context,
498
+ break_context: nil,
499
+ self_type: module_context.module_type,
500
+ type_env: type_env,
501
+ lvar_env: lvar_env
502
+ )
503
+
504
+ self.class.new(
505
+ checker: checker,
506
+ source: source,
507
+ annotations: annots,
508
+ typing: typing,
509
+ context: body_context
510
+ )
511
+ end
512
+
439
513
  def for_branch(node, truthy_vars: Set.new, type_case_override: nil, break_context: context.break_context)
440
514
  annots = source.annotations(block: node, factory: checker.factory, current_module: current_namespace)
441
515
 
@@ -565,6 +639,7 @@ module Steep
565
639
  add_typing(node, type: AST::Builtin.any_type)
566
640
  else
567
641
  rhs_result = synthesize(rhs, hint: hint || context.lvar_env.declared_types[name]&.type)
642
+
568
643
  constr = rhs_result.constr.update_lvar_env do |lvar_env|
569
644
  lvar_env.assign(name, node: node, type: rhs_result.type) do |declared_type, actual_type, result|
570
645
  typing.add_error(Errors::IncompatibleAssignment.new(node: node,
@@ -1037,10 +1112,10 @@ module Steep
1037
1112
  case child.type
1038
1113
  when :pair
1039
1114
  key, value = child.children
1040
- key_types << synthesize(key).type.yield_self do |type|
1115
+ key_types << synthesize(key, hint: key_hint).type.yield_self do |type|
1041
1116
  select_super_type(type, key_hint)
1042
1117
  end
1043
- value_types << synthesize(value).type.yield_self do |type|
1118
+ value_types << synthesize(value, hint: value_hint).type.yield_self do |type|
1044
1119
  select_super_type(type, value_hint)
1045
1120
  end
1046
1121
  when :kwsplat
@@ -1115,6 +1190,25 @@ module Steep
1115
1190
  add_typing(node, type: AST::Builtin.nil_type)
1116
1191
  end
1117
1192
 
1193
+ when :sclass
1194
+ yield_self do
1195
+ type, constr = synthesize(node.children[0])
1196
+ constructor = constr.for_sclass(node, type)
1197
+
1198
+ constructor.typing.add_context_for_node(node, context: constructor.context)
1199
+ constructor.typing.add_context_for_body(node, context: constructor.context)
1200
+
1201
+ constructor.synthesize(node.children[1]) if node.children[1]
1202
+
1203
+ if constructor.module_context.instance_definition && module_context.module_definition
1204
+ if constructor.module_context.instance_definition.type_name == module_context.module_definition.type_name
1205
+ module_context.defined_module_methods.merge(constructor.module_context.defined_instance_methods)
1206
+ end
1207
+ end
1208
+
1209
+ add_typing(node, type: AST::Builtin.nil_type)
1210
+ end
1211
+
1118
1212
  when :self
1119
1213
  add_typing node, type: AST::Types::Self.new
1120
1214
 
@@ -1256,7 +1350,7 @@ module Steep
1256
1350
  end
1257
1351
  end
1258
1352
  else
1259
- [select_super_type(synthesize(e).type, element_hint)]
1353
+ [select_super_type(synthesize(e, hint: element_hint).type, element_hint)]
1260
1354
  end
1261
1355
  end
1262
1356
  array_type = AST::Builtin::Array.instance_type(AST::Types::Union.build(types: element_types))
@@ -1992,9 +2086,11 @@ module Steep
1992
2086
  end
1993
2087
  end
1994
2088
  rescue => exn
1995
- $stderr.puts exn.inspect
1996
- exn.backtrace.each do |t|
1997
- $stderr.puts t
2089
+ case exn
2090
+ when RBS::NoTypeFoundError, RBS::NoMixinFoundError, RBS::NoSuperclassFoundError, RBS::InvalidTypeApplicationError
2091
+ # ignore known RBS errors.
2092
+ else
2093
+ Steep.log_error(exn, message: "Unexpected error in #type_send: #{exn.message} (#{exn.class})")
1998
2094
  end
1999
2095
 
2000
2096
  fallback_to_any node do
@@ -2750,13 +2846,18 @@ module Steep
2750
2846
  end
2751
2847
 
2752
2848
  def validate_method_definitions(node, module_name)
2849
+ module_name_1 = checker.factory.type_name_1(module_name.name)
2850
+ member_decl_count = checker.factory.env.class_decls[module_name_1].decls.count {|d| d.decl.each_member.count > 0 }
2851
+
2852
+ return unless member_decl_count == 1
2853
+
2753
2854
  expected_instance_method_names = (module_context.instance_definition&.methods || {}).each.with_object(Set[]) do |(name, method), set|
2754
- if method.implemented_in == module_context.instance_definition.declaration
2855
+ if method.implemented_in == module_context.instance_definition.type_name
2755
2856
  set << name
2756
2857
  end
2757
2858
  end
2758
2859
  expected_module_method_names = (module_context.module_definition&.methods || {}).each.with_object(Set[]) do |(name, method), set|
2759
- if method.implemented_in == module_context.module_definition.declaration
2860
+ if method.implemented_in == module_context.module_definition.type_name
2760
2861
  set << name
2761
2862
  end
2762
2863
  end
@@ -2948,7 +3049,7 @@ module Steep
2948
3049
  def to_instance_type(type, args: nil)
2949
3050
  args = args || case type
2950
3051
  when AST::Types::Name::Class, AST::Types::Name::Module
2951
- checker.factory.env.find_class(checker.factory.type_name_1(type.name)).type_params.each.map { AST::Builtin.any_type }
3052
+ checker.factory.env.class_decls[checker.factory.type_name_1(type.name)].type_params.each.map { AST::Builtin.any_type }
2952
3053
  else
2953
3054
  raise "unexpected type to to_instance_type: #{type}"
2954
3055
  end
@@ -31,8 +31,8 @@ module Steep
31
31
  annotations.const_types.each do |name, type|
32
32
  env.set(const: name, type: type)
33
33
  end
34
- signatures.name_to_global.each do |name, global|
35
- type = signatures.absolute_type(global.type, namespace: RBS::Namespace.root) {|ty| ty.name.absolute! }
34
+ signatures.global_decls.each do |name, entry|
35
+ type = entry.decl.type
36
36
  env.set(gvar: name, type: subtyping.factory.type(type))
37
37
  end
38
38
  end
@@ -95,6 +95,12 @@ module Steep
95
95
  end_pos = node.loc.end.begin_pos
96
96
  add_context(begin_pos..end_pos, context: context)
97
97
 
98
+ when :sclass
99
+ name_node = node.children[0]
100
+ begin_pos = name_node.loc.expression.end_pos
101
+ end_pos = node.loc.end.begin_pos
102
+ add_context(begin_pos..end_pos, context: context)
103
+
98
104
  when :def, :defs
99
105
  args_node = case node.type
100
106
  when :def
@@ -1,3 +1,3 @@
1
1
  module Steep
2
- VERSION = "0.16.3"
2
+ VERSION = "0.20.0"
3
3
  end
@@ -1,9 +1,10 @@
1
- extension Object (X)
1
+
2
+ class Object
2
3
  def try: [A] { (instance) -> A } -> A
3
4
  def f: -> Object
4
5
  end
5
6
 
6
- extension Kernel (X)
7
+ module Kernel
7
8
  def new_module_method: () -> void
8
9
  end
9
10
 
@@ -2,7 +2,6 @@ class NumberLike
2
2
  def to_number: -> Integer
3
3
  end
4
4
 
5
- extension Integer (NumberLike)
6
- def `+`: (NumberLike) -> NumberLike
7
- | super
5
+ class Integer
6
+ overload def `+`: (NumberLike) -> NumberLike
8
7
  end
@@ -1,12 +1,12 @@
1
1
  class A
2
2
  def foo: -> _Foo
3
3
  def hello: -> void
4
- end
5
4
 
6
- class A::Object
7
- def object?: -> bool
8
- end
5
+ class Object
6
+ def object?: -> bool
7
+ end
9
8
 
10
- interface A::_Foo
11
- def foo: -> Object
9
+ interface _Foo
10
+ def foo: -> Object
11
+ end
12
12
  end
@@ -41,5 +41,5 @@ Gem::Specification.new do |spec|
41
41
  spec.add_runtime_dependency "rainbow", ">= 2.2.2", "< 4.0"
42
42
  spec.add_runtime_dependency "listen", "~> 3.1"
43
43
  spec.add_runtime_dependency "language_server-protocol", "~> 3.14.0.2"
44
- spec.add_runtime_dependency "rbs", "~> 0.3.1"
44
+ spec.add_runtime_dependency "rbs", ">= 0.6.0", '< 0.7.0'
45
45
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: steep
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.16.3
4
+ version: 0.20.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Soutaro Matsumoto
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-05-27 00:00:00.000000000 Z
11
+ date: 2020-07-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -188,16 +188,22 @@ dependencies:
188
188
  name: rbs
189
189
  requirement: !ruby/object:Gem::Requirement
190
190
  requirements:
191
- - - "~>"
191
+ - - ">="
192
+ - !ruby/object:Gem::Version
193
+ version: 0.6.0
194
+ - - "<"
192
195
  - !ruby/object:Gem::Version
193
- version: 0.3.1
196
+ version: 0.7.0
194
197
  type: :runtime
195
198
  prerelease: false
196
199
  version_requirements: !ruby/object:Gem::Requirement
197
200
  requirements:
198
- - - "~>"
201
+ - - ">="
202
+ - !ruby/object:Gem::Version
203
+ version: 0.6.0
204
+ - - "<"
199
205
  - !ruby/object:Gem::Version
200
- version: 0.3.1
206
+ version: 0.7.0
201
207
  description: Gradual Typing for Ruby
202
208
  email:
203
209
  - matsumoto@soutaro.com