steep 0.48.0 → 0.50.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +25 -0
- data/Gemfile +3 -1
- data/Gemfile.lock +3 -3
- data/lib/steep/ast/types/any.rb +2 -0
- data/lib/steep/ast/types/boolean.rb +2 -0
- data/lib/steep/ast/types/bot.rb +2 -0
- data/lib/steep/ast/types/class.rb +2 -0
- data/lib/steep/ast/types/factory.rb +1 -1
- data/lib/steep/ast/types/helper.rb +8 -0
- data/lib/steep/ast/types/instance.rb +2 -0
- data/lib/steep/ast/types/intersection.rb +4 -0
- data/lib/steep/ast/types/literal.rb +2 -0
- data/lib/steep/ast/types/logic.rb +2 -0
- data/lib/steep/ast/types/name.rb +6 -0
- data/lib/steep/ast/types/nil.rb +2 -0
- data/lib/steep/ast/types/proc.rb +9 -0
- data/lib/steep/ast/types/record.rb +4 -0
- data/lib/steep/ast/types/self.rb +2 -0
- data/lib/steep/ast/types/top.rb +2 -0
- data/lib/steep/ast/types/tuple.rb +4 -0
- data/lib/steep/ast/types/union.rb +4 -0
- data/lib/steep/ast/types/var.rb +2 -0
- data/lib/steep/ast/types/void.rb +2 -0
- data/lib/steep/cli.rb +5 -0
- data/lib/steep/diagnostic/ruby.rb +13 -0
- data/lib/steep/drivers/check.rb +3 -2
- data/lib/steep/drivers/langserver.rb +2 -2
- data/lib/steep/drivers/stats.rb +1 -0
- data/lib/steep/drivers/utils/jobs_count.rb +1 -1
- data/lib/steep/drivers/watch.rb +1 -1
- data/lib/steep/interface/function.rb +9 -0
- data/lib/steep/project.rb +15 -1
- data/lib/steep/server/interaction_worker.rb +2 -2
- data/lib/steep/server/master.rb +9 -4
- data/lib/steep/server/type_check_worker.rb +19 -4
- data/lib/steep/server/worker_process.rb +15 -6
- data/lib/steep/services/goto_service.rb +19 -4
- data/lib/steep/services/type_check_service.rb +2 -0
- data/lib/steep/signature/validator.rb +12 -5
- data/lib/steep/subtyping/check.rb +23 -2
- data/lib/steep/type_construction.rb +116 -39
- data/lib/steep/type_inference/block_params.rb +31 -3
- data/lib/steep/version.rb +1 -1
- data/smoke/diagnostics/proc_type_expected.rb +3 -0
- data/smoke/diagnostics/test_expectations.yml +12 -0
- data/smoke/tsort/a.rb +1 -1
- data/smoke/tsort/test_expectations.yml +1 -63
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6ff552f6d8f112693dc9969f20d851ddbc6d7d2f16cebd45f802a5d703618b58
|
4
|
+
data.tar.gz: 723464fe34c81c3e83b66338dfc6fd3e7c3da2aaf30c1fc48116c7de794ca961
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bf9f83791cfb636c65a26f404fb164fa7fc3906376e36a79a1ca4ae7eeab8020e23c5b9ce5e649a38ed79080d0aa2c00fe53a5cce8a1c76c259237f38880bbf2
|
7
|
+
data.tar.gz: 25bd9e11db283acdfc957682860e674d544b82be1b5a68bc87ca96888907966b721301c937cdaa3e06bf0226ec82fa8c78eacfaf4987637a601f75ca8d8e950c
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,31 @@
|
|
2
2
|
|
3
3
|
## master
|
4
4
|
|
5
|
+
# 0.50.0 (2022-03-22)
|
6
|
+
|
7
|
+
* CLI option for override steep command at spawn worker ([\#511](https://github.com/soutaro/steep/pull/511))
|
8
|
+
* LSP related improvements for Sublime LSP ([\#513](https://github.com/soutaro/steep/pull/513))
|
9
|
+
* Support Windows environment ([\#514](https://github.com/soutaro/steep/pull/514))
|
10
|
+
* Let `&:foo` proc work with methods with optional parameters ([\#516](https://github.com/soutaro/steep/pull/516))
|
11
|
+
* Fix unexpected error when or-asgn/and-asgn ([\#517](https://github.com/soutaro/steep/pull/517))
|
12
|
+
* Fix goto-definition from method call inside block ([\#518](https://github.com/soutaro/steep/pull/518))
|
13
|
+
* Better splat in array typing ([\#519](https://github.com/soutaro/steep/pull/519))
|
14
|
+
|
15
|
+
## 0.49.1 (2022-03-11)
|
16
|
+
|
17
|
+
* Fix lambda typing ([\#506](https://github.com/soutaro/steep/pull/506))
|
18
|
+
* Validate type descendants ([\#507](https://github.com/soutaro/steep/pull/507))
|
19
|
+
* Fix print error with absolute path ([\#508](https://github.com/soutaro/steep/pull/508))
|
20
|
+
* Skip non-target ruby code on `steep stats` ([\#509](https://github.com/soutaro/steep/pull/509))
|
21
|
+
|
22
|
+
## 0.49.0 (2022-03-08)
|
23
|
+
|
24
|
+
* Better typing for `#flat_map` ([\#504](https://github.com/soutaro/steep/pull/504))
|
25
|
+
* Support lambdas (`->`) with block ([\#503](https://github.com/soutaro/steep/pull/503))
|
26
|
+
* Let proc type be `::Proc` class instance ([\#502](https://github.com/soutaro/steep/pull/502))
|
27
|
+
* Disable contextual typing on `bool` type ([\#501](https://github.com/soutaro/steep/pull/501))
|
28
|
+
* Type check `return` without value ([\#500](https://github.com/soutaro/steep/pull/500))
|
29
|
+
|
5
30
|
## 0.48.0 (2022-03-07)
|
6
31
|
|
7
32
|
Steep supports all of the new features of RBS 2. 🎉
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
steep (0.
|
4
|
+
steep (0.50.0)
|
5
5
|
activesupport (>= 5.1)
|
6
6
|
language_server-protocol (>= 3.15, < 4.0)
|
7
7
|
listen (~> 3.0)
|
@@ -24,7 +24,7 @@ PATH
|
|
24
24
|
GEM
|
25
25
|
remote: https://rubygems.org/
|
26
26
|
specs:
|
27
|
-
activesupport (7.0.2.
|
27
|
+
activesupport (7.0.2.3)
|
28
28
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
29
29
|
i18n (>= 1.6, < 2)
|
30
30
|
minitest (>= 5.1)
|
@@ -41,7 +41,7 @@ GEM
|
|
41
41
|
minitest (5.15.0)
|
42
42
|
minitest-hooks (1.5.0)
|
43
43
|
minitest (> 5.3)
|
44
|
-
parallel (1.
|
44
|
+
parallel (1.22.0)
|
45
45
|
parser (3.1.1.0)
|
46
46
|
ast (~> 2.4.1)
|
47
47
|
rainbow (3.1.1)
|
data/lib/steep/ast/types/any.rb
CHANGED
data/lib/steep/ast/types/bot.rb
CHANGED
data/lib/steep/ast/types/name.rb
CHANGED
@@ -72,6 +72,10 @@ module Steep
|
|
72
72
|
end
|
73
73
|
end
|
74
74
|
|
75
|
+
def each_child(&block)
|
76
|
+
args.each(&block)
|
77
|
+
end
|
78
|
+
|
75
79
|
include Helper::ChildrenLevel
|
76
80
|
|
77
81
|
def level
|
@@ -98,6 +102,8 @@ module Steep
|
|
98
102
|
def with_location(new_location)
|
99
103
|
self.class.new(name: name, location: new_location)
|
100
104
|
end
|
105
|
+
|
106
|
+
include Helper::NoChild
|
101
107
|
end
|
102
108
|
|
103
109
|
class Instance < Applying
|
data/lib/steep/ast/types/nil.rb
CHANGED
data/lib/steep/ast/types/proc.rb
CHANGED
@@ -90,6 +90,15 @@ module Steep
|
|
90
90
|
def block_required?
|
91
91
|
block && !block.optional?
|
92
92
|
end
|
93
|
+
|
94
|
+
def each_child(&block)
|
95
|
+
if block_given?
|
96
|
+
type.each_child(&block)
|
97
|
+
self.block&.type&.each_child(&block)
|
98
|
+
else
|
99
|
+
enum_for :each_child
|
100
|
+
end
|
101
|
+
end
|
93
102
|
end
|
94
103
|
end
|
95
104
|
end
|
data/lib/steep/ast/types/self.rb
CHANGED
data/lib/steep/ast/types/top.rb
CHANGED
data/lib/steep/ast/types/var.rb
CHANGED
data/lib/steep/ast/types/void.rb
CHANGED
data/lib/steep/cli.rb
CHANGED
@@ -72,6 +72,11 @@ module Steep
|
|
72
72
|
opts.on("-j N", "--jobs=N", "Specify the number of type check workers (defaults: #{default})") do |count|
|
73
73
|
command.jobs_count = Integer(count) if Integer(count) > 0
|
74
74
|
end
|
75
|
+
|
76
|
+
command.steep_command = "steep"
|
77
|
+
opts.on("--steep-command=COMMAND", "Specify command to exec Steep CLI for worker (defaults: steep)") do |cmd|
|
78
|
+
command.steep_command = cmd
|
79
|
+
end
|
75
80
|
end
|
76
81
|
|
77
82
|
def process_init
|
@@ -669,6 +669,19 @@ module Steep
|
|
669
669
|
end
|
670
670
|
end
|
671
671
|
|
672
|
+
class ProcTypeExpected < Base
|
673
|
+
attr_reader :type
|
674
|
+
|
675
|
+
def initialize(node:, type:)
|
676
|
+
super(node: node)
|
677
|
+
@type = type
|
678
|
+
end
|
679
|
+
|
680
|
+
def header_line
|
681
|
+
"Proc type is expected but `#{type.to_s}` is specified"
|
682
|
+
end
|
683
|
+
end
|
684
|
+
|
672
685
|
class UnsupportedSyntax < Base
|
673
686
|
attr_reader :message
|
674
687
|
|
data/lib/steep/drivers/check.rb
CHANGED
@@ -39,6 +39,7 @@ module Steep
|
|
39
39
|
steepfile: project.steepfile_path,
|
40
40
|
args: command_line_patterns,
|
41
41
|
delay_shutdown: true,
|
42
|
+
steep_command: steep_command,
|
42
43
|
count: jobs_count
|
43
44
|
)
|
44
45
|
|
@@ -214,8 +215,8 @@ module Steep
|
|
214
215
|
total = errors.sum {|notification| notification[:diagnostics].size }
|
215
216
|
|
216
217
|
errors.each do |notification|
|
217
|
-
path =
|
218
|
-
buffer = RBS::Buffer.new(name: path, content: path.read)
|
218
|
+
path = Pathname(URI.parse(notification[:uri]).path)
|
219
|
+
buffer = RBS::Buffer.new(name: project.relative_path(path), content: path.read)
|
219
220
|
printer = DiagnosticPrinter.new(buffer: buffer, stdout: stdout)
|
220
221
|
|
221
222
|
notification[:diagnostics].each do |diag|
|
@@ -37,8 +37,8 @@ module Steep
|
|
37
37
|
def run
|
38
38
|
@project = load_config()
|
39
39
|
|
40
|
-
interaction_worker = Server::WorkerProcess.spawn_worker(:interaction, name: "interaction", steepfile: project.steepfile_path)
|
41
|
-
typecheck_workers = Server::WorkerProcess.spawn_typecheck_workers(steepfile: project.steepfile_path, args: [], count: jobs_count)
|
40
|
+
interaction_worker = Server::WorkerProcess.spawn_worker(:interaction, name: "interaction", steepfile: project.steepfile_path, steep_command: steep_command)
|
41
|
+
typecheck_workers = Server::WorkerProcess.spawn_typecheck_workers(steepfile: project.steepfile_path, args: [], steep_command: steep_command, count: jobs_count)
|
42
42
|
|
43
43
|
master = Server::Master.new(
|
44
44
|
project: project,
|
data/lib/steep/drivers/stats.rb
CHANGED
data/lib/steep/drivers/watch.rb
CHANGED
@@ -41,7 +41,7 @@ module Steep
|
|
41
41
|
server_reader = LanguageServer::Protocol::Transport::Io::Reader.new(server_read)
|
42
42
|
server_writer = LanguageServer::Protocol::Transport::Io::Writer.new(server_write)
|
43
43
|
|
44
|
-
typecheck_workers = Server::WorkerProcess.spawn_typecheck_workers(steepfile: project.steepfile_path, args: dirs.map(&:to_s), count: jobs_count)
|
44
|
+
typecheck_workers = Server::WorkerProcess.spawn_typecheck_workers(steepfile: project.steepfile_path, args: dirs.map(&:to_s), steep_command: steep_command, count: jobs_count)
|
45
45
|
|
46
46
|
master = Server::Master.new(
|
47
47
|
project: project,
|
@@ -879,6 +879,11 @@ module Steep
|
|
879
879
|
!has_positional? && !has_keywords?
|
880
880
|
end
|
881
881
|
|
882
|
+
# Returns true if all arguments are non-required.
|
883
|
+
def optional?
|
884
|
+
required.empty? && required_keywords.empty?
|
885
|
+
end
|
886
|
+
|
882
887
|
# self + params returns a new params for overloading.
|
883
888
|
#
|
884
889
|
def +(other)
|
@@ -952,6 +957,10 @@ module Steep
|
|
952
957
|
)
|
953
958
|
end
|
954
959
|
|
960
|
+
def each_child(&block)
|
961
|
+
each_type(&block)
|
962
|
+
end
|
963
|
+
|
955
964
|
def each_type(&block)
|
956
965
|
if block_given?
|
957
966
|
params.each_type(&block)
|
data/lib/steep/project.rb
CHANGED
@@ -16,7 +16,21 @@ module Steep
|
|
16
16
|
steepfile_path.parent
|
17
17
|
end
|
18
18
|
|
19
|
-
def relative_path(
|
19
|
+
def relative_path(orig_path)
|
20
|
+
path = if Gem.win_platform?
|
21
|
+
path_str = URI.decode_www_form_component(
|
22
|
+
orig_path.to_s.delete_prefix("/")
|
23
|
+
)
|
24
|
+
unless path_str.start_with?(%r{[a-z]:/}i)
|
25
|
+
# FIXME: Sometimes drive letter is missing, taking from base_dir
|
26
|
+
path_str = base_dir.to_s.split("/")[0] + "/" + path_str
|
27
|
+
end
|
28
|
+
Pathname.new(
|
29
|
+
path_str
|
30
|
+
)
|
31
|
+
else
|
32
|
+
orig_path
|
33
|
+
end
|
20
34
|
path.relative_path_from(base_dir)
|
21
35
|
end
|
22
36
|
|
@@ -89,7 +89,7 @@ module Steep
|
|
89
89
|
end
|
90
90
|
|
91
91
|
LSP::Interface::Hover.new(
|
92
|
-
contents: { kind: "markdown", value: format_hover(content) },
|
92
|
+
contents: { kind: "markdown", value: format_hover(content)&.gsub(/<!--(?~-->)-->/, "") },
|
93
93
|
range: range
|
94
94
|
)
|
95
95
|
end
|
@@ -271,7 +271,7 @@ HOVER
|
|
271
271
|
),
|
272
272
|
end: LanguageServer::Protocol::Interface::Position.new(
|
273
273
|
line: job.line - 1,
|
274
|
-
character: job.column
|
274
|
+
character: job.column
|
275
275
|
)
|
276
276
|
)
|
277
277
|
|
data/lib/steep/server/master.rb
CHANGED
@@ -49,9 +49,14 @@ module Steep
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def checking_path?(path)
|
52
|
-
library_paths.
|
53
|
-
|
54
|
-
|
52
|
+
[library_paths, signature_paths, code_paths].any? do |paths|
|
53
|
+
if Gem.win_platform?
|
54
|
+
# FIXME: Sometimes drive letter is missing, so comparing without drive letter.
|
55
|
+
paths.any? {|p| p.to_s.split("/", 2)[1] == path.to_s.split("/", 2)[1]}
|
56
|
+
else
|
57
|
+
paths.include?(path)
|
58
|
+
end
|
59
|
+
end
|
55
60
|
end
|
56
61
|
|
57
62
|
def checked(path)
|
@@ -739,7 +744,7 @@ module Steep
|
|
739
744
|
{ kind: "end" }
|
740
745
|
else
|
741
746
|
progress_string = ("▮"*(percentage/5)) + ("▯"*(20 - percentage/5))
|
742
|
-
{ kind: "report", percentage: percentage, message: "#{progress_string}
|
747
|
+
{ kind: "report", percentage: percentage, message: "#{progress_string}" }
|
743
748
|
end
|
744
749
|
|
745
750
|
job_queue << SendMessageJob.to_client(
|
@@ -135,6 +135,21 @@ module Steep
|
|
135
135
|
end
|
136
136
|
|
137
137
|
def handle_job(job)
|
138
|
+
job_path = if job.respond_to?(:path)
|
139
|
+
if Gem.win_platform?
|
140
|
+
# FIXME: Sometimes drive letter is missing, using base_dir
|
141
|
+
if job.path.to_s.start_with?(%r{/[a-z](:|%3A)/}i)
|
142
|
+
job.path.to_s
|
143
|
+
else
|
144
|
+
"/#{project.base_dir.to_s.split("/").first}/#{job.path}"
|
145
|
+
end
|
146
|
+
else
|
147
|
+
job.path.to_s
|
148
|
+
end
|
149
|
+
else
|
150
|
+
nil
|
151
|
+
end
|
152
|
+
|
138
153
|
case job
|
139
154
|
when StartTypeCheckJob
|
140
155
|
Steep.logger.info { "Processing StartTypeCheckJob for guid=#{job.guid}" }
|
@@ -149,7 +164,7 @@ module Steep
|
|
149
164
|
writer.write(
|
150
165
|
method: :"textDocument/publishDiagnostics",
|
151
166
|
params: LSP::Interface::PublishDiagnosticsParams.new(
|
152
|
-
uri: URI.parse(
|
167
|
+
uri: URI.parse(job_path).tap {|uri| uri.scheme = "file"},
|
153
168
|
diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq
|
154
169
|
)
|
155
170
|
)
|
@@ -167,7 +182,7 @@ module Steep
|
|
167
182
|
writer.write(
|
168
183
|
method: :"textDocument/publishDiagnostics",
|
169
184
|
params: LSP::Interface::PublishDiagnosticsParams.new(
|
170
|
-
uri: URI.parse(
|
185
|
+
uri: URI.parse(job_path).tap {|uri| uri.scheme = "file"},
|
171
186
|
diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq.compact
|
172
187
|
)
|
173
188
|
)
|
@@ -186,7 +201,7 @@ module Steep
|
|
186
201
|
writer.write(
|
187
202
|
method: :"textDocument/publishDiagnostics",
|
188
203
|
params: LSP::Interface::PublishDiagnosticsParams.new(
|
189
|
-
uri: URI.parse(
|
204
|
+
uri: URI.parse(job_path).tap {|uri| uri.scheme = "file"},
|
190
205
|
diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq.compact
|
191
206
|
)
|
192
207
|
)
|
@@ -268,7 +283,7 @@ module Steep
|
|
268
283
|
line = job.params[:position][:line] + 1
|
269
284
|
column = job.params[:position][:character]
|
270
285
|
|
271
|
-
goto_service = Services::GotoService.new(type_check: service)
|
286
|
+
goto_service = Services::GotoService.new(type_check: service, assignment: assignment)
|
272
287
|
locations =
|
273
288
|
case
|
274
289
|
when job.definition?
|
@@ -18,13 +18,17 @@ module Steep
|
|
18
18
|
@index = index
|
19
19
|
end
|
20
20
|
|
21
|
-
def self.spawn_worker(type, name:, steepfile:, options: [], delay_shutdown: false, index: nil)
|
22
|
-
|
21
|
+
def self.spawn_worker(type, name:, steepfile:, steep_command: "steep", options: [], delay_shutdown: false, index: nil)
|
22
|
+
args = ["--name=#{name}", "--steepfile=#{steepfile}"]
|
23
|
+
args << (%w(debug info warn error fatal unknown)[Steep.logger.level].yield_self {|log_level| "--log-level=#{log_level}" })
|
24
|
+
if Steep.log_output.is_a?(String)
|
25
|
+
args << "--log-output=#{Steep.log_output}"
|
26
|
+
end
|
23
27
|
command = case type
|
24
28
|
when :interaction
|
25
|
-
[
|
29
|
+
[steep_command, "worker", "--interaction", *args, *options]
|
26
30
|
when :typecheck
|
27
|
-
[
|
31
|
+
[steep_command, "worker", "--typecheck", *args, *options]
|
28
32
|
else
|
29
33
|
raise "Unknown type: #{type}"
|
30
34
|
end
|
@@ -33,7 +37,11 @@ module Steep
|
|
33
37
|
command << "--delay-shutdown"
|
34
38
|
end
|
35
39
|
|
36
|
-
stdin, stdout, thread =
|
40
|
+
stdin, stdout, thread = if Gem.win_platform?
|
41
|
+
Open3.popen2(*command, new_pgroup: true)
|
42
|
+
else
|
43
|
+
Open3.popen2(*command, pgroup: true)
|
44
|
+
end
|
37
45
|
stderr = nil
|
38
46
|
|
39
47
|
writer = LanguageServer::Protocol::Transport::Io::Writer.new(stdin)
|
@@ -42,11 +50,12 @@ module Steep
|
|
42
50
|
new(reader: reader, writer: writer, stderr: stderr, wait_thread: thread, name: name, index: index)
|
43
51
|
end
|
44
52
|
|
45
|
-
def self.spawn_typecheck_workers(steepfile:, args:, count: [Etc.nprocessors - 1, 1].max, delay_shutdown: false)
|
53
|
+
def self.spawn_typecheck_workers(steepfile:, args:, steep_command: "steep", count: [Etc.nprocessors - 1, 1].max, delay_shutdown: false)
|
46
54
|
count.times.map do |i|
|
47
55
|
spawn_worker(:typecheck,
|
48
56
|
name: "typecheck@#{i}",
|
49
57
|
steepfile: steepfile,
|
58
|
+
steep_command: steep_command,
|
50
59
|
options: ["--max-index=#{count}", "--index=#{i}", *args],
|
51
60
|
delay_shutdown: delay_shutdown,
|
52
61
|
index: i)
|
@@ -21,10 +21,11 @@ module Steep
|
|
21
21
|
end
|
22
22
|
TypeNameQuery = Struct.new(:name, keyword_init: true)
|
23
23
|
|
24
|
-
attr_reader :type_check
|
24
|
+
attr_reader :type_check, :assignment
|
25
25
|
|
26
|
-
def initialize(type_check:)
|
26
|
+
def initialize(type_check:, assignment:)
|
27
27
|
@type_check = type_check
|
28
|
+
@assignment = assignment
|
28
29
|
end
|
29
30
|
|
30
31
|
def project
|
@@ -78,7 +79,17 @@ module Steep
|
|
78
79
|
end
|
79
80
|
end
|
80
81
|
|
81
|
-
|
82
|
+
# Drop un-assigned paths here.
|
83
|
+
# The path assignment makes sense only for `.rbs` files, because un-assigned `.rb` files are already skipped since they are not type checked.
|
84
|
+
#
|
85
|
+
locations.uniq.select do |loc|
|
86
|
+
case loc
|
87
|
+
when RBS::Location
|
88
|
+
assignment =~ loc.name
|
89
|
+
else
|
90
|
+
true
|
91
|
+
end
|
92
|
+
end
|
82
93
|
end
|
83
94
|
|
84
95
|
def test_ast_location(loc, line:, column:)
|
@@ -100,6 +111,7 @@ module Steep
|
|
100
111
|
typing, signature = type_check_path(target: target, path: relative_path, content: source.content, line: line, column: column)
|
101
112
|
if typing
|
102
113
|
node, *parents = typing.source.find_nodes(line: line, column: column)
|
114
|
+
|
103
115
|
if node
|
104
116
|
case node.type
|
105
117
|
when :const, :casgn
|
@@ -125,7 +137,10 @@ module Steep
|
|
125
137
|
end
|
126
138
|
when :send
|
127
139
|
if test_ast_location(node.location.selector, line: line, column: column)
|
128
|
-
|
140
|
+
if (parent = parents[0]) && parent.type == :block && parent.children[0] == node
|
141
|
+
node = parents[0]
|
142
|
+
end
|
143
|
+
|
129
144
|
case call = typing.call_of(node: node)
|
130
145
|
when TypeInference::MethodCall::Typed, TypeInference::MethodCall::Error
|
131
146
|
call.method_decls.each do |decl|
|
@@ -269,6 +269,8 @@ module Steep
|
|
269
269
|
end
|
270
270
|
|
271
271
|
def typecheck_source(path:, target: project.target_for_source_path(path), &block)
|
272
|
+
return unless target
|
273
|
+
|
272
274
|
Steep.logger.tagged "#typecheck_source(path=#{path})" do
|
273
275
|
Steep.measure "typecheck" do
|
274
276
|
signature_service = signature_services[target.name]
|
@@ -89,11 +89,7 @@ module Steep
|
|
89
89
|
end
|
90
90
|
end
|
91
91
|
|
92
|
-
def
|
93
|
-
Steep.logger.debug "#{Location.to_string type.location}: Validating #{type}..."
|
94
|
-
|
95
|
-
validator.validate_type type, context: [RBS::Namespace.root]
|
96
|
-
|
92
|
+
def validate_type_application(type)
|
97
93
|
name, type_params, type_args =
|
98
94
|
case type
|
99
95
|
when RBS::Types::ClassInstance
|
@@ -123,6 +119,17 @@ module Steep
|
|
123
119
|
validate_type_application_constraints(type.name, type_params, type_args, location: type.location)
|
124
120
|
end
|
125
121
|
end
|
122
|
+
|
123
|
+
type.each_type do |child|
|
124
|
+
validate_type_application(child)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def validate_type(type)
|
129
|
+
Steep.logger.debug "#{Location.to_string type.location}: Validating #{type}..."
|
130
|
+
|
131
|
+
validator.validate_type type, context: [RBS::Namespace.root]
|
132
|
+
validate_type_application(type)
|
126
133
|
end
|
127
134
|
|
128
135
|
def ancestor_to_type(ancestor)
|
@@ -347,7 +347,7 @@ module Steep
|
|
347
347
|
|
348
348
|
when relation.super_type.is_a?(AST::Types::Union)
|
349
349
|
Any(relation) do |result|
|
350
|
-
relation.super_type.types.each do |super_type|
|
350
|
+
relation.super_type.types.sort_by {|ty| (path = hole_path(ty)) ? -path.size : 1 }.each do |super_type|
|
351
351
|
rel = Relation.new(sub_type: relation.sub_type, super_type: super_type)
|
352
352
|
result.add(rel) do
|
353
353
|
check_type(rel)
|
@@ -357,7 +357,7 @@ module Steep
|
|
357
357
|
|
358
358
|
when relation.sub_type.is_a?(AST::Types::Intersection)
|
359
359
|
Any(relation) do |result|
|
360
|
-
relation.sub_type.types.each do |sub_type|
|
360
|
+
relation.sub_type.types.sort_by {|ty| (path = hole_path(ty)) ? -path.size : 1 }.each do |sub_type|
|
361
361
|
rel = Relation.new(sub_type: sub_type, super_type: relation.super_type)
|
362
362
|
result.add(rel) do
|
363
363
|
check_type(rel)
|
@@ -483,6 +483,9 @@ module Steep
|
|
483
483
|
check_interface(relation.map {|type| factory.interface(type, private: false) })
|
484
484
|
end
|
485
485
|
|
486
|
+
when relation.sub_type.is_a?(AST::Types::Proc) && AST::Builtin::Proc.instance_type?(relation.super_type)
|
487
|
+
Success(relation)
|
488
|
+
|
486
489
|
when relation.super_type.is_a?(AST::Types::Literal)
|
487
490
|
case
|
488
491
|
when relation.super_type.value == true && AST::Builtin::TrueClass.instance_type?(relation.sub_type)
|
@@ -971,6 +974,24 @@ module Steep
|
|
971
974
|
def expand_alias(type, &block)
|
972
975
|
factory.expand_alias(type, &block)
|
973
976
|
end
|
977
|
+
|
978
|
+
# Returns the shortest type paths for one of the _unknown_ type variables.
|
979
|
+
# Returns nil if there is no path.
|
980
|
+
def hole_path(type, path = [])
|
981
|
+
case type
|
982
|
+
when AST::Types::Var
|
983
|
+
if constraints.unknown?(type.name)
|
984
|
+
[type]
|
985
|
+
else
|
986
|
+
nil
|
987
|
+
end
|
988
|
+
else
|
989
|
+
paths = type.each_child.map do |ty|
|
990
|
+
hole_path(ty, path)&.unshift(ty)
|
991
|
+
end
|
992
|
+
paths.compact.min_by(&:size)
|
993
|
+
end
|
994
|
+
end
|
974
995
|
end
|
975
996
|
end
|
976
997
|
end
|
@@ -1005,7 +1005,7 @@ module Steep
|
|
1005
1005
|
yield_self do
|
1006
1006
|
send_node, params, body = node.children
|
1007
1007
|
if send_node.type == :lambda
|
1008
|
-
type_lambda(node,
|
1008
|
+
type_lambda(node, params_node: params, body_node: body, type_hint: hint)
|
1009
1009
|
else
|
1010
1010
|
type_send(node, send_node: send_node, block_params: params, block_body: body, unwrap: send_node.type == :csend)
|
1011
1011
|
end
|
@@ -1024,7 +1024,7 @@ module Steep
|
|
1024
1024
|
params = Parser::AST::Node.new(:args, arg_nodes)
|
1025
1025
|
|
1026
1026
|
if send_node.type == :lambda
|
1027
|
-
type_lambda(node,
|
1027
|
+
type_lambda(node, params_node: params, body_node: body, type_hint: hint)
|
1028
1028
|
else
|
1029
1029
|
type_send(node, send_node: send_node, block_params: params, block_body: body, unwrap: send_node.type == :csend)
|
1030
1030
|
end
|
@@ -1181,9 +1181,9 @@ module Steep
|
|
1181
1181
|
|
1182
1182
|
when :return
|
1183
1183
|
yield_self do
|
1184
|
-
|
1185
|
-
method_return_type = expand_alias(method_context&.return_type)
|
1184
|
+
method_return_type = expand_alias(method_context&.return_type)
|
1186
1185
|
|
1186
|
+
if node.children.size > 0
|
1187
1187
|
return_types = node.children.map do |value|
|
1188
1188
|
synthesize(
|
1189
1189
|
value,
|
@@ -1201,20 +1201,23 @@ module Steep
|
|
1201
1201
|
AST::Builtin::Array.instance_type(union_type(*return_types))
|
1202
1202
|
end
|
1203
1203
|
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
1204
|
+
else
|
1205
|
+
value_type = AST::Builtin.nil_type
|
1206
|
+
end
|
1207
1207
|
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1208
|
+
if method_return_type
|
1209
|
+
unless method_return_type.is_a?(AST::Types::Void)
|
1210
|
+
result = check_relation(sub_type: value_type, super_type: method_return_type)
|
1211
|
+
|
1212
|
+
if result.failure?
|
1213
|
+
typing.add_error(
|
1214
|
+
Diagnostic::Ruby::ReturnTypeMismatch.new(
|
1215
|
+
node: node,
|
1216
|
+
expected: method_context&.return_type,
|
1217
|
+
actual: value_type,
|
1218
|
+
result: result
|
1216
1219
|
)
|
1217
|
-
|
1220
|
+
)
|
1218
1221
|
end
|
1219
1222
|
end
|
1220
1223
|
end
|
@@ -2272,13 +2275,10 @@ module Steep
|
|
2272
2275
|
type, constr = synthesize(rhs, hint: hint)
|
2273
2276
|
constr.ivasgn(asgn, type)
|
2274
2277
|
when :send
|
2275
|
-
|
2276
|
-
|
2277
|
-
|
2278
|
-
|
2279
|
-
asgn.children[2],
|
2280
|
-
rhs
|
2281
|
-
])
|
2278
|
+
children = asgn.children.dup
|
2279
|
+
children[1] = :"#{children[1]}="
|
2280
|
+
send_arg_nodes = [*children, rhs]
|
2281
|
+
rhs_ = node.updated(:send, send_arg_nodes)
|
2282
2282
|
node_type = case node.type
|
2283
2283
|
when :or_asgn
|
2284
2284
|
:or
|
@@ -2345,11 +2345,11 @@ module Steep
|
|
2345
2345
|
interface = calculate_interface(param_type, private: true)
|
2346
2346
|
method = interface.methods[value.children[0]]
|
2347
2347
|
if method
|
2348
|
-
return_types = method.method_types.
|
2349
|
-
method_type.type.params.
|
2350
|
-
|
2351
|
-
|
2352
|
-
|
2348
|
+
return_types = method.method_types.filter_map do |method_type|
|
2349
|
+
if method_type.type.params.optional?
|
2350
|
+
method_type.type.return_type
|
2351
|
+
end
|
2352
|
+
end
|
2353
2353
|
|
2354
2354
|
unless return_types.empty?
|
2355
2355
|
type = AST::Types::Proc.new(
|
@@ -2357,7 +2357,7 @@ module Steep
|
|
2357
2357
|
params: Interface::Function::Params.empty.with_first_param(
|
2358
2358
|
Interface::Function::Params::PositionalParams::Required.new(param_type)
|
2359
2359
|
),
|
2360
|
-
return_type:
|
2360
|
+
return_type: return_types[0],
|
2361
2361
|
location: nil
|
2362
2362
|
),
|
2363
2363
|
block: nil
|
@@ -2724,34 +2724,89 @@ module Steep
|
|
2724
2724
|
end
|
2725
2725
|
end
|
2726
2726
|
|
2727
|
-
def
|
2727
|
+
def optional_proc?(type)
|
2728
|
+
if type.is_a?(AST::Types::Union)
|
2729
|
+
if type.types.size == 2
|
2730
|
+
if type.types.find {|t| t.is_a?(AST::Types::Nil) }
|
2731
|
+
if proc_type = type.types.find {|t| t.is_a?(AST::Types::Proc) }
|
2732
|
+
proc_type
|
2733
|
+
end
|
2734
|
+
end
|
2735
|
+
end
|
2736
|
+
end
|
2737
|
+
end
|
2738
|
+
|
2739
|
+
def type_lambda(node, params_node:, body_node:, type_hint:)
|
2728
2740
|
block_annotations = source.annotations(block: node, factory: checker.factory, current_module: current_namespace)
|
2729
|
-
params = TypeInference::BlockParams.from_node(
|
2741
|
+
params = TypeInference::BlockParams.from_node(params_node, annotations: block_annotations)
|
2742
|
+
|
2743
|
+
type_hint = deep_expand_alias(type_hint) if type_hint
|
2730
2744
|
|
2731
2745
|
case type_hint
|
2732
2746
|
when AST::Types::Proc
|
2733
2747
|
params_hint = type_hint.type.params
|
2734
2748
|
return_hint = type_hint.type.return_type
|
2749
|
+
block_hint = type_hint.block
|
2735
2750
|
end
|
2736
2751
|
|
2737
2752
|
block_constr = for_block(
|
2738
2753
|
block_params: params,
|
2739
2754
|
block_param_hint: params_hint,
|
2740
2755
|
block_type_hint: return_hint,
|
2756
|
+
block_block_hint: block_hint,
|
2741
2757
|
block_annotations: block_annotations,
|
2742
2758
|
node_type_hint: nil
|
2743
2759
|
)
|
2744
2760
|
|
2745
2761
|
block_constr.typing.add_context_for_body(node, context: block_constr.context)
|
2746
2762
|
|
2763
|
+
default_proc_function =
|
2764
|
+
Interface::Function.new(
|
2765
|
+
params: Interface::Function::Params.empty,
|
2766
|
+
return_type: AST::Builtin.any_type,
|
2767
|
+
location: nil
|
2768
|
+
)
|
2769
|
+
|
2747
2770
|
params.params.each do |param|
|
2748
2771
|
_, block_constr = block_constr.synthesize(param.node, hint: param.type)
|
2749
2772
|
end
|
2750
2773
|
|
2751
|
-
|
2774
|
+
block =
|
2775
|
+
if block_param = params.block_param
|
2776
|
+
if block_param_type = block_param.type
|
2777
|
+
case block_param_type
|
2778
|
+
when AST::Types::Proc
|
2779
|
+
Interface::Block.new(type: block_param_type.type, optional: false)
|
2780
|
+
else
|
2781
|
+
if proc_type = optional_proc?(block_param_type)
|
2782
|
+
Interface::Block.new(type: proc_type.type, optional: true)
|
2783
|
+
else
|
2784
|
+
block_constr.typing.add_error(
|
2785
|
+
Diagnostic::Ruby::ProcTypeExpected.new(
|
2786
|
+
node: block_param.node,
|
2787
|
+
type: block_param_type
|
2788
|
+
)
|
2789
|
+
)
|
2790
|
+
|
2791
|
+
Interface::Block.new(
|
2792
|
+
type: Interface::Function.new(
|
2793
|
+
params: Interface::Function::Params.empty,
|
2794
|
+
return_type: AST::Builtin.any_type,
|
2795
|
+
location: nil
|
2796
|
+
),
|
2797
|
+
optional: false
|
2798
|
+
)
|
2799
|
+
end
|
2800
|
+
end
|
2801
|
+
else
|
2802
|
+
block_hint
|
2803
|
+
end
|
2804
|
+
end
|
2805
|
+
|
2806
|
+
if body_node
|
2752
2807
|
return_type = block_constr.synthesize_block(
|
2753
2808
|
node: node,
|
2754
|
-
block_body:
|
2809
|
+
block_body: body_node,
|
2755
2810
|
block_type_hint: return_hint
|
2756
2811
|
)
|
2757
2812
|
|
@@ -2779,7 +2834,7 @@ module Steep
|
|
2779
2834
|
return_type: return_type,
|
2780
2835
|
location: nil
|
2781
2836
|
),
|
2782
|
-
block:
|
2837
|
+
block: block
|
2783
2838
|
)
|
2784
2839
|
|
2785
2840
|
add_typing node, type: block_type
|
@@ -3246,7 +3301,7 @@ module Steep
|
|
3246
3301
|
|
3247
3302
|
if method_type.block
|
3248
3303
|
# Method accepts block
|
3249
|
-
pairs = method_type.block && block_params_&.zip(method_type.block.type.params)
|
3304
|
+
pairs = method_type.block && block_params_&.zip(method_type.block.type.params, nil)
|
3250
3305
|
|
3251
3306
|
if pairs
|
3252
3307
|
# Block parameters are compatible with the block type
|
@@ -3254,6 +3309,7 @@ module Steep
|
|
3254
3309
|
block_params: block_params_,
|
3255
3310
|
block_param_hint: method_type.block.type.params,
|
3256
3311
|
block_type_hint: method_type.block.type.return_type,
|
3312
|
+
block_block_hint: nil,
|
3257
3313
|
block_annotations: block_annotations,
|
3258
3314
|
node_type_hint: method_type.type.return_type
|
3259
3315
|
)
|
@@ -3503,13 +3559,14 @@ module Steep
|
|
3503
3559
|
message: "Unsupported block params pattern, probably masgn?"
|
3504
3560
|
)
|
3505
3561
|
)
|
3506
|
-
block_params = TypeInference::BlockParams.new(leading_params: [], optional_params: [], rest_param: nil, trailing_params: [])
|
3562
|
+
block_params = TypeInference::BlockParams.new(leading_params: [], optional_params: [], rest_param: nil, trailing_params: [], block_param: nil)
|
3507
3563
|
end
|
3508
3564
|
|
3509
3565
|
block_constr = for_block(
|
3510
3566
|
block_params: block_params,
|
3511
3567
|
block_param_hint: nil,
|
3512
3568
|
block_type_hint: AST::Builtin.any_type,
|
3569
|
+
block_block_hint: nil,
|
3513
3570
|
block_annotations: block_annotations,
|
3514
3571
|
node_type_hint: AST::Builtin.any_type
|
3515
3572
|
)
|
@@ -3536,8 +3593,8 @@ module Steep
|
|
3536
3593
|
end
|
3537
3594
|
end
|
3538
3595
|
|
3539
|
-
def for_block(block_params:, block_param_hint:, block_type_hint:, block_annotations:, node_type_hint:)
|
3540
|
-
block_param_pairs = block_param_hint && block_params.zip(block_param_hint)
|
3596
|
+
def for_block(block_params:, block_param_hint:, block_type_hint:, block_block_hint:, block_annotations:, node_type_hint:)
|
3597
|
+
block_param_pairs = block_param_hint && block_params.zip(block_param_hint, block_block_hint)
|
3541
3598
|
|
3542
3599
|
param_types_hash = {}
|
3543
3600
|
if block_param_pairs
|
@@ -3888,6 +3945,20 @@ module Steep
|
|
3888
3945
|
constr.add_typing(node, type: AST::Types::Tuple.new(types: element_types))
|
3889
3946
|
end
|
3890
3947
|
|
3948
|
+
def try_convert(type, method)
|
3949
|
+
interface = checker.factory.interface(type, private: false)
|
3950
|
+
if entry = interface.methods[method]
|
3951
|
+
method_type = entry.method_types.find do |method_type|
|
3952
|
+
method_type.type.params.optional?
|
3953
|
+
end
|
3954
|
+
|
3955
|
+
method_type.type.return_type
|
3956
|
+
end
|
3957
|
+
rescue => exn
|
3958
|
+
Steep.log_error(exn, message: "Unexpected error when converting #{type.to_s} with #{method}")
|
3959
|
+
nil
|
3960
|
+
end
|
3961
|
+
|
3891
3962
|
def try_array_type(node, hint)
|
3892
3963
|
element_hint = hint ? hint.args[0] : nil
|
3893
3964
|
|
@@ -3898,8 +3969,14 @@ module Steep
|
|
3898
3969
|
case child.type
|
3899
3970
|
when :splat
|
3900
3971
|
type, constr = constr.synthesize(child.children[0], hint: hint)
|
3901
|
-
|
3972
|
+
|
3973
|
+
type = try_convert(type, :to_a) || type
|
3974
|
+
|
3975
|
+
case
|
3976
|
+
when AST::Builtin::Array.instance_type?(type)
|
3902
3977
|
element_types << type.args[0]
|
3978
|
+
when type.is_a?(AST::Types::Tuple)
|
3979
|
+
element_types.push(*type.types)
|
3903
3980
|
else
|
3904
3981
|
element_types.push(*flatten_array_elements(type))
|
3905
3982
|
end
|
@@ -29,12 +29,14 @@ module Steep
|
|
29
29
|
attr_reader :optional_params
|
30
30
|
attr_reader :rest_param
|
31
31
|
attr_reader :trailing_params
|
32
|
+
attr_reader :block_param
|
32
33
|
|
33
|
-
def initialize(leading_params:, optional_params:, rest_param:, trailing_params:)
|
34
|
+
def initialize(leading_params:, optional_params:, rest_param:, trailing_params:, block_param:)
|
34
35
|
@leading_params = leading_params
|
35
36
|
@optional_params = optional_params
|
36
37
|
@rest_param = rest_param
|
37
38
|
@trailing_params = trailing_params
|
39
|
+
@block_param = block_param
|
38
40
|
end
|
39
41
|
|
40
42
|
def params
|
@@ -43,6 +45,7 @@ module Steep
|
|
43
45
|
params.push(*optional_params)
|
44
46
|
params.push rest_param if rest_param
|
45
47
|
params.push(*trailing_params)
|
48
|
+
params.push(block_param) if block_param
|
46
49
|
end
|
47
50
|
end
|
48
51
|
|
@@ -51,6 +54,7 @@ module Steep
|
|
51
54
|
optional_params = []
|
52
55
|
rest_param = nil
|
53
56
|
trailing_params = []
|
57
|
+
block_param = nil
|
54
58
|
|
55
59
|
default_params = leading_params
|
56
60
|
|
@@ -72,6 +76,9 @@ module Steep
|
|
72
76
|
when :restarg
|
73
77
|
default_params = trailing_params
|
74
78
|
rest_param = Param.new(var: var, type: type, value: nil, node: arg)
|
79
|
+
when :blockarg
|
80
|
+
block_param = Param.new(var: var, type: type, value: nil, node: arg)
|
81
|
+
break
|
75
82
|
end
|
76
83
|
end
|
77
84
|
|
@@ -79,7 +86,8 @@ module Steep
|
|
79
86
|
leading_params: leading_params,
|
80
87
|
optional_params: optional_params,
|
81
88
|
rest_param: rest_param,
|
82
|
-
trailing_params: trailing_params
|
89
|
+
trailing_params: trailing_params,
|
90
|
+
block_param: block_param
|
83
91
|
)
|
84
92
|
end
|
85
93
|
|
@@ -141,7 +149,7 @@ module Steep
|
|
141
149
|
)
|
142
150
|
end
|
143
151
|
|
144
|
-
def zip(params_type)
|
152
|
+
def zip(params_type, block)
|
145
153
|
if trailing_params.any?
|
146
154
|
Steep.logger.error "Block definition with trailing required parameters are not supported yet"
|
147
155
|
end
|
@@ -204,6 +212,26 @@ module Steep
|
|
204
212
|
end
|
205
213
|
end
|
206
214
|
end
|
215
|
+
|
216
|
+
if block_param
|
217
|
+
if block
|
218
|
+
proc_type =
|
219
|
+
if block.optional?
|
220
|
+
AST::Types::Union.build(
|
221
|
+
types: [
|
222
|
+
AST::Types::Proc.new(type: block.type, block: nil),
|
223
|
+
AST::Builtin.nil_type
|
224
|
+
]
|
225
|
+
)
|
226
|
+
else
|
227
|
+
AST::Types::Proc.new(type: block.type, block: nil)
|
228
|
+
end
|
229
|
+
|
230
|
+
zip << [block_param, proc_type]
|
231
|
+
else
|
232
|
+
zip << [block_param, AST::Builtin.nil_type]
|
233
|
+
end
|
234
|
+
end
|
207
235
|
end
|
208
236
|
end
|
209
237
|
|
data/lib/steep/version.rb
CHANGED
@@ -332,6 +332,18 @@
|
|
332
332
|
severity: ERROR
|
333
333
|
message: Type `::Integer` does not have method `foo`
|
334
334
|
code: Ruby::NoMethod
|
335
|
+
- file: proc_type_expected.rb
|
336
|
+
diagnostics:
|
337
|
+
- range:
|
338
|
+
start:
|
339
|
+
line: 1
|
340
|
+
character: 4
|
341
|
+
end:
|
342
|
+
line: 1
|
343
|
+
character: 10
|
344
|
+
severity: ERROR
|
345
|
+
message: Proc type is expected but `::Integer` is specified
|
346
|
+
code: Ruby::ProcTypeExpected
|
335
347
|
- file: required_block_missing.rb
|
336
348
|
diagnostics:
|
337
349
|
- range:
|
data/smoke/tsort/a.rb
CHANGED
@@ -1,63 +1 @@
|
|
1
|
-
---
|
2
|
-
- file: a.rb
|
3
|
-
diagnostics:
|
4
|
-
- range:
|
5
|
-
start:
|
6
|
-
line: 7
|
7
|
-
character: 0
|
8
|
-
end:
|
9
|
-
line: 7
|
10
|
-
character: 38
|
11
|
-
severity: ERROR
|
12
|
-
message: |-
|
13
|
-
Cannot assign a value of type `^() -> ::Hash[::Integer, ::Array[::Integer]]` to a variable of type `^() { (::Integer) -> void } -> void`
|
14
|
-
^() -> ::Hash[::Integer, ::Array[::Integer]] <: ^() { (::Integer) -> void } -> void
|
15
|
-
code: Ruby::IncompatibleAssignment
|
16
|
-
- range:
|
17
|
-
start:
|
18
|
-
line: 7
|
19
|
-
character: 34
|
20
|
-
end:
|
21
|
-
line: 7
|
22
|
-
character: 35
|
23
|
-
severity: ERROR
|
24
|
-
message: Cannot detect the type of the expression
|
25
|
-
code: Ruby::FallbackAny
|
26
|
-
- range:
|
27
|
-
start:
|
28
|
-
line: 9
|
29
|
-
character: 0
|
30
|
-
end:
|
31
|
-
line: 9
|
32
|
-
character: 41
|
33
|
-
severity: ERROR
|
34
|
-
message: |-
|
35
|
-
Cannot assign a value of type `^(::Integer) -> ::Enumerator[::Integer, ::Array[::Integer]]` to a variable of type `^(::Integer) { (::Integer) -> void } -> void`
|
36
|
-
^(::Integer) -> ::Enumerator[::Integer, ::Array[::Integer]] <: ^(::Integer) { (::Integer) -> void } -> void
|
37
|
-
code: Ruby::IncompatibleAssignment
|
38
|
-
- range:
|
39
|
-
start:
|
40
|
-
line: 9
|
41
|
-
character: 37
|
42
|
-
end:
|
43
|
-
line: 9
|
44
|
-
character: 38
|
45
|
-
severity: ERROR
|
46
|
-
message: Cannot detect the type of the expression
|
47
|
-
code: Ruby::FallbackAny
|
48
|
-
- range:
|
49
|
-
start:
|
50
|
-
line: 12
|
51
|
-
character: 0
|
52
|
-
end:
|
53
|
-
line: 12
|
54
|
-
character: 39
|
55
|
-
severity: ERROR
|
56
|
-
message: |-
|
57
|
-
Cannot assign a value of type `::Array[::Integer]` to a variable of type `::Array[::String]`
|
58
|
-
::Array[::Integer] <: ::Array[::String]
|
59
|
-
::Integer <: ::String
|
60
|
-
::Numeric <: ::String
|
61
|
-
::Object <: ::String
|
62
|
-
::BasicObject <: ::String
|
63
|
-
code: Ruby::IncompatibleAssignment
|
1
|
+
--- []
|
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.
|
4
|
+
version: 0.50.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: 2022-03-
|
11
|
+
date: 2022-03-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: parser
|
@@ -356,6 +356,7 @@ files:
|
|
356
356
|
- smoke/diagnostics/method_return_type_annotation_mismatch.rb
|
357
357
|
- smoke/diagnostics/missing_keyword.rb
|
358
358
|
- smoke/diagnostics/no_method.rb
|
359
|
+
- smoke/diagnostics/proc_type_expected.rb
|
359
360
|
- smoke/diagnostics/required_block_missing.rb
|
360
361
|
- smoke/diagnostics/return_type_mismatch.rb
|
361
362
|
- smoke/diagnostics/test_expectations.yml
|