steep 0.17.0 → 0.21.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: f60fa7be29b63a36a6f25cb94138d558d0bbaa652cb40ab5f2a4a24f1a0d58ac
4
- data.tar.gz: 83582c3c37c5afefe079a545860e96a8edce020b891755b49f6a1cbdf53cce04
3
+ metadata.gz: 6109c6ce90265363be0ef33fe06e517577f3e884a6fc20c921f5d716c4916de1
4
+ data.tar.gz: 1bcba16bfab23e534eb40b7302dd21e43b487ba6441a02d0da403ac4df54d788
5
5
  SHA512:
6
- metadata.gz: 38e917a0030c6f0f993d6d0bd6bd9e26bb955cdd08609802df87992f7242933f03f3b35311c53fec9e6f74a12cb5d2237c5e03d6461fc56f44d019b8011ed12e
7
- data.tar.gz: 5a5fa1b3502b23d3a9e6c1391de6c3313e8309adbbf353589eda27ed356414201ec2c6f6cdceb01b5f2afd8425a777a3d02921e509ba15674295c65f04bbdc0e
6
+ metadata.gz: b8bffda05cd158a3ce849fca2722fcb0d62de0d6307a88d4fa0d3758a7965aef706bccab3b4a634a3343e2c0bbd1cc87bec8e5f5b31cfa52e19a6d3f2931b5eb
7
+ data.tar.gz: 57cb080c69a71fb31f52bd4e65e37ca1719f46718b02632d2c5af3ff72c8b34eba56f098831558fd7df18afbdec0fd6802d0fbb326c5cb4086c147ba11b5447f
@@ -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.21.0 (2020-07-20)
6
+
7
+ * Fix LSP hover ([#168](https://github.com/soutaro/steep/pull/168))
8
+ * Nominal subtyping ([#167](https://github.com/soutaro/steep/pull/167))
9
+
10
+ ## 0.20.0 (2020-07-17)
11
+
12
+ * Support singleton class definitions ([#166](https://github.com/soutaro/steep/pull/166))
13
+
14
+ ## 0.19.0 (2020-07-12)
15
+
16
+ * Update RBS. ([#157](https://github.com/soutaro/steep/pull/157))
17
+ * No `initialize` in completion. ([#164](https://github.com/soutaro/steep/pull/164))
18
+ * Granular typing option setup. ([#163](https://github.com/soutaro/steep/pull/163))
19
+
20
+ ## 0.18.0 (2020-07-06)
21
+
22
+ * Sort result of `Pathname#glob` ([#154](https://github.com/soutaro/steep/pull/154))
23
+ * Sort methods in LanguageServer to return non-inherited methods first ([#159](https://github.com/soutaro/steep/pull/159))
24
+
25
+ ## 0.17.1 (2020-06-15)
26
+
27
+ * Allow RBS gem to be 0.4 ([#153](https://github.com/soutaro/steep/pull/153))
28
+
5
29
  ## 0.17.0 (2020-06-13)
6
30
 
7
31
  * Fix `steep watch` and `steep langserver` to correctly handle error message filterings based on options ([#152](https://github.com/soutaro/steep/pull/152))
@@ -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
@@ -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
@@ -52,6 +52,13 @@ module Steep
52
52
  true
53
53
  end
54
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
55
62
  end
56
63
  end
57
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
 
@@ -95,8 +95,8 @@ module Steep
95
95
  ```
96
96
  HOVER
97
97
  if content.definition
98
- if content.definition.comment
99
- string << "\n----\n\n#{content.definition.comment.string}"
98
+ if content.definition.comments
99
+ string << "\n----\n\n#{content.definition.comments.map(&:string).join("\n\n")}"
100
100
  end
101
101
 
102
102
  string << "\n----\n\n#{content.definition.method_types.map {|x| "- `#{x}`\n" }.join()}"
@@ -110,8 +110,8 @@ HOVER
110
110
  def #{content.method_name}: #{content.method_type}
111
111
  ```
112
112
  HOVER
113
- if (comment = content.definition.comment)
114
- string << "\n----\n\n#{comment.string}\n"
113
+ if (comment = content.comment_string)
114
+ string << "\n----\n\n#{comment}\n"
115
115
  end
116
116
 
117
117
  if content.definition.method_types.size > 1
@@ -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|