steep 1.2.1 → 1.3.0.pre.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +28 -0
- data/Gemfile.lock +4 -4
- data/Gemfile.steep +1 -1
- data/Gemfile.steep.lock +13 -3
- data/Steepfile +0 -1
- data/bin/steep-prof +1 -1
- data/lib/steep/annotation_parser.rb +34 -28
- data/lib/steep/ast/annotation.rb +16 -5
- data/lib/steep/ast/node/type_application.rb +74 -0
- data/lib/steep/ast/node/type_assertion.rb +56 -0
- data/lib/steep/ast/types/factory.rb +5 -1
- data/lib/steep/ast/types/helper.rb +4 -3
- data/lib/steep/ast/types/logic.rb +4 -0
- data/lib/steep/diagnostic/helper.rb +2 -1
- data/lib/steep/diagnostic/lsp_formatter.rb +3 -1
- data/lib/steep/diagnostic/ruby.rb +70 -5
- data/lib/steep/diagnostic/signature.rb +21 -8
- data/lib/steep/drivers/check.rb +2 -2
- data/lib/steep/drivers/checkfile.rb +2 -2
- data/lib/steep/drivers/langserver.rb +2 -2
- data/lib/steep/drivers/stats.rb +2 -2
- data/lib/steep/drivers/utils/jobs_option.rb +0 -4
- data/lib/steep/drivers/watch.rb +1 -1
- data/lib/steep/drivers/worker.rb +0 -1
- data/lib/steep/server/lsp_formatter.rb +13 -3
- data/lib/steep/server/master.rb +4 -1
- data/lib/steep/server/worker_process.rb +91 -14
- data/lib/steep/services/completion_provider.rb +2 -1
- data/lib/steep/services/goto_service.rb +2 -1
- data/lib/steep/services/hover_provider/rbs.rb +7 -7
- data/lib/steep/services/hover_provider/ruby.rb +21 -5
- data/lib/steep/services/signature_service.rb +23 -4
- data/lib/steep/services/type_check_service.rb +4 -4
- data/lib/steep/signature/validator.rb +36 -13
- data/lib/steep/source.rb +189 -71
- data/lib/steep/type_construction.rb +246 -135
- data/lib/steep/type_inference/logic_type_interpreter.rb +3 -1
- data/lib/steep/version.rb +1 -1
- data/lib/steep.rb +2 -0
- data/rbs_collection.steep.lock.yaml +27 -10
- data/rbs_collection.steep.yaml +0 -1
- data/sig/shims/exception.rbs +4 -0
- data/sig/shims/parser/comment.rbs +33 -0
- data/sig/shims/parser.rbs +30 -2
- data/sig/steep/annotation_parser.rbs +59 -0
- data/sig/steep/ast/annotation.rbs +21 -26
- data/sig/steep/ast/node/type_application.rbs +31 -0
- data/sig/steep/ast/node/type_assertion.rbs +26 -0
- data/sig/steep/ast/types/any.rbs +1 -1
- data/sig/steep/ast/types/boolean.rbs +1 -1
- data/sig/steep/ast/types/bot.rbs +1 -1
- data/sig/steep/ast/types/class.rbs +1 -1
- data/sig/steep/ast/types/factory.rbs +0 -2
- data/sig/steep/ast/types/helper.rbs +6 -3
- data/sig/steep/ast/types/instance.rbs +1 -1
- data/sig/steep/ast/types/intersection.rbs +1 -1
- data/sig/steep/ast/types/logic.rbs +2 -0
- data/sig/steep/ast/types/name.rbs +2 -2
- data/sig/steep/ast/types/nil.rbs +1 -1
- data/sig/steep/ast/types/record.rbs +1 -1
- data/sig/steep/ast/types/self.rbs +1 -1
- data/sig/steep/ast/types/top.rbs +2 -2
- data/sig/steep/ast/types/tuple.rbs +1 -1
- data/sig/steep/ast/types/union.rbs +1 -1
- data/sig/steep/ast/types/var.rbs +2 -2
- data/sig/steep/ast/types/void.rbs +1 -1
- data/sig/steep/diagnostic/helper.rbs +9 -3
- data/sig/steep/diagnostic/lsp_formatter.rbs +12 -8
- data/sig/steep/diagnostic/ruby.rbs +62 -8
- data/sig/steep/diagnostic/signature.rbs +118 -85
- data/sig/steep/drivers/utils/jobs_option.rbs +0 -2
- data/sig/steep/drivers/worker.rbs +11 -13
- data/sig/steep/range_extension.rbs +7 -0
- data/sig/steep/server/lsp_formatter.rbs +14 -7
- data/sig/steep/server/worker_process.rbs +74 -12
- data/sig/steep/services/hover_provider/rbs.rbs +27 -7
- data/sig/steep/services/hover_provider/ruby.rbs +18 -4
- data/sig/steep/services/hover_provider/singleton_methods.rbs +1 -1
- data/sig/steep/services/signature_service.rbs +14 -0
- data/sig/steep/services/type_check_service.rbs +2 -2
- data/sig/steep/signature/validator.rbs +76 -0
- data/sig/steep/source.rbs +54 -30
- data/sig/steep/type_construction.rbs +85 -27
- data/sig/steep/type_inference/method_call.rbs +1 -1
- data/sig/steep.rbs +2 -0
- data/smoke/diagnostics-rbs/inherit-module.rbs +2 -0
- data/smoke/diagnostics-rbs/test_expectations.yml +12 -0
- data/steep.gemspec +1 -1
- metadata +16 -6
@@ -11,9 +11,7 @@ module Steep
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def header_line
|
14
|
-
|
15
|
-
puts io
|
16
|
-
end.string
|
14
|
+
raise
|
17
15
|
end
|
18
16
|
|
19
17
|
def detail_lines
|
@@ -25,7 +23,9 @@ module Steep
|
|
25
23
|
end
|
26
24
|
|
27
25
|
def path
|
28
|
-
location
|
26
|
+
if location
|
27
|
+
Pathname(location.buffer.name)
|
28
|
+
end
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
@@ -166,7 +166,6 @@ module Steep
|
|
166
166
|
class RecursiveAlias < Base
|
167
167
|
attr_reader :class_name
|
168
168
|
attr_reader :names
|
169
|
-
attr_reader :location
|
170
169
|
|
171
170
|
def initialize(class_name:, names:, location:)
|
172
171
|
super(location: location)
|
@@ -284,7 +283,6 @@ module Steep
|
|
284
283
|
|
285
284
|
class InstanceVariableTypeError < Base
|
286
285
|
attr_reader :name
|
287
|
-
attr_reader :variable
|
288
286
|
attr_reader :var_type
|
289
287
|
attr_reader :parent_type
|
290
288
|
|
@@ -318,7 +316,7 @@ module Steep
|
|
318
316
|
private
|
319
317
|
|
320
318
|
def mixin_name
|
321
|
-
case member
|
319
|
+
case mem = member
|
322
320
|
when RBS::AST::Members::Prepend
|
323
321
|
"prepend"
|
324
322
|
when RBS::AST::Members::Include
|
@@ -329,6 +327,19 @@ module Steep
|
|
329
327
|
end
|
330
328
|
end
|
331
329
|
|
330
|
+
class InheritModuleError < Base
|
331
|
+
attr_reader :super_class
|
332
|
+
|
333
|
+
def initialize(super_class)
|
334
|
+
super(location: super_class.location)
|
335
|
+
@super_class = super_class
|
336
|
+
end
|
337
|
+
|
338
|
+
def header_line
|
339
|
+
"Cannot inherit from a module `#{super_class.name}`"
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
332
343
|
class UnexpectedError < Base
|
333
344
|
attr_reader :message
|
334
345
|
|
@@ -427,7 +438,7 @@ module Steep
|
|
427
438
|
Diagnostic::Signature::RecursiveAlias.new(
|
428
439
|
class_name: error.type.name,
|
429
440
|
names: error.defs.map(&:name),
|
430
|
-
location: error.defs[0].original
|
441
|
+
location: error.defs[0].original&.location
|
431
442
|
)
|
432
443
|
when RBS::RecursiveAncestorError
|
433
444
|
Diagnostic::Signature::RecursiveAncestor.new(
|
@@ -462,6 +473,8 @@ module Steep
|
|
462
473
|
nonregular_type: factory.type(error.diagnostic.nonregular_type),
|
463
474
|
location: error.location
|
464
475
|
)
|
476
|
+
when RBS::InheritModuleError
|
477
|
+
Diagnostic::Signature::InheritModuleError.new(error.super_decl)
|
465
478
|
else
|
466
479
|
raise error
|
467
480
|
end
|
data/lib/steep/drivers/check.rb
CHANGED
@@ -36,11 +36,11 @@ module Steep
|
|
36
36
|
server_reader = LanguageServer::Protocol::Transport::Io::Reader.new(server_read)
|
37
37
|
server_writer = LanguageServer::Protocol::Transport::Io::Writer.new(server_write)
|
38
38
|
|
39
|
-
typecheck_workers = Server::WorkerProcess.
|
39
|
+
typecheck_workers = Server::WorkerProcess.start_typecheck_workers(
|
40
40
|
steepfile: project.steepfile_path,
|
41
41
|
args: command_line_patterns,
|
42
42
|
delay_shutdown: true,
|
43
|
-
steep_command: jobs_option.
|
43
|
+
steep_command: jobs_option.steep_command,
|
44
44
|
count: jobs_option.jobs_count_value
|
45
45
|
)
|
46
46
|
|
@@ -101,11 +101,11 @@ module Steep
|
|
101
101
|
|
102
102
|
Steep.logger.info { "Starting #{count} workers for #{files.size} files..." }
|
103
103
|
|
104
|
-
typecheck_workers = Server::WorkerProcess.
|
104
|
+
typecheck_workers = Server::WorkerProcess.start_typecheck_workers(
|
105
105
|
steepfile: project.steepfile_path,
|
106
106
|
args: [],
|
107
107
|
delay_shutdown: true,
|
108
|
-
steep_command: jobs_option.
|
108
|
+
steep_command: jobs_option.steep_command,
|
109
109
|
count: count
|
110
110
|
)
|
111
111
|
|
@@ -35,8 +35,8 @@ module Steep
|
|
35
35
|
def run
|
36
36
|
@project = load_config()
|
37
37
|
|
38
|
-
interaction_worker = Server::WorkerProcess.
|
39
|
-
typecheck_workers = Server::WorkerProcess.
|
38
|
+
interaction_worker = Server::WorkerProcess.start_worker(:interaction, name: "interaction", steepfile: project.steepfile_path, steep_command: jobs_option.steep_command)
|
39
|
+
typecheck_workers = Server::WorkerProcess.start_typecheck_workers(steepfile: project.steepfile_path, args: [], steep_command: jobs_option.steep_command, count: jobs_option.jobs_count_value)
|
40
40
|
|
41
41
|
master = Server::Master.new(
|
42
42
|
project: project,
|
data/lib/steep/drivers/stats.rb
CHANGED
@@ -126,11 +126,11 @@ module Steep
|
|
126
126
|
server_reader = LanguageServer::Protocol::Transport::Io::Reader.new(server_read)
|
127
127
|
server_writer = LanguageServer::Protocol::Transport::Io::Writer.new(server_write)
|
128
128
|
|
129
|
-
typecheck_workers = Server::WorkerProcess.
|
129
|
+
typecheck_workers = Server::WorkerProcess.start_typecheck_workers(
|
130
130
|
steepfile: project.steepfile_path,
|
131
131
|
delay_shutdown: true,
|
132
132
|
args: command_line_patterns,
|
133
|
-
steep_command: jobs_option.
|
133
|
+
steep_command: jobs_option.steep_command,
|
134
134
|
count: jobs_option.jobs_count_value
|
135
135
|
)
|
136
136
|
|
data/lib/steep/drivers/watch.rb
CHANGED
@@ -42,7 +42,7 @@ module Steep
|
|
42
42
|
server_reader = LanguageServer::Protocol::Transport::Io::Reader.new(server_read)
|
43
43
|
server_writer = LanguageServer::Protocol::Transport::Io::Writer.new(server_write)
|
44
44
|
|
45
|
-
typecheck_workers = Server::WorkerProcess.
|
45
|
+
typecheck_workers = Server::WorkerProcess.start_typecheck_workers(steepfile: project.steepfile_path, args: dirs.map(&:to_s), steep_command: jobs_option.steep_command, count: jobs_option.jobs_count_value)
|
46
46
|
|
47
47
|
master = Server::Master.new(
|
48
48
|
project: project,
|
data/lib/steep/drivers/worker.rb
CHANGED
@@ -17,6 +17,8 @@ module Steep
|
|
17
17
|
def to_s
|
18
18
|
unless @array.empty?
|
19
19
|
@array.join("\n\n----\n\n")
|
20
|
+
else
|
21
|
+
""
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
@@ -83,7 +85,7 @@ module Steep
|
|
83
85
|
#{decl.method_type}
|
84
86
|
```
|
85
87
|
|
86
|
-
#{
|
88
|
+
#{comment.string.gsub(/\A([ \t]*\n)+/, "")}
|
87
89
|
EOM
|
88
90
|
end
|
89
91
|
end
|
@@ -108,10 +110,10 @@ EOM
|
|
108
110
|
end
|
109
111
|
when HoverProvider::Ruby::ConstantContent
|
110
112
|
CommentBuilder.build do |builder|
|
111
|
-
if content.class_or_module?
|
113
|
+
if decl = content.class_or_module?
|
112
114
|
builder << <<EOM
|
113
115
|
```rbs
|
114
|
-
#{declaration_summary(
|
116
|
+
#{declaration_summary(decl.primary.decl)}
|
115
117
|
```
|
116
118
|
EOM
|
117
119
|
end
|
@@ -141,6 +143,14 @@ EOM
|
|
141
143
|
builder << comment.string
|
142
144
|
end
|
143
145
|
end
|
146
|
+
when HoverProvider::Ruby::TypeAssertionContent
|
147
|
+
CommentBuilder.build do |builder|
|
148
|
+
builder << <<-EOM
|
149
|
+
`#{content.asserted_type.to_s}`
|
150
|
+
|
151
|
+
↑ Converted from `#{content.original_type.to_s}`
|
152
|
+
EOM
|
153
|
+
end
|
144
154
|
when HoverProvider::RBS::ClassContent
|
145
155
|
CommentBuilder.build do |builder|
|
146
156
|
builder << <<EOM
|
data/lib/steep/server/master.rb
CHANGED
@@ -796,7 +796,10 @@ module Steep
|
|
796
796
|
|
797
797
|
Steep.logger.info "Sending $/typecheck/start notifications"
|
798
798
|
typecheck_workers.each do |worker|
|
799
|
-
assignment = Services::PathAssignment.new(
|
799
|
+
assignment = Services::PathAssignment.new(
|
800
|
+
max_index: typecheck_workers.size,
|
801
|
+
index: worker.index || raise
|
802
|
+
)
|
800
803
|
|
801
804
|
job_queue << SendMessageJob.to_worker(
|
802
805
|
worker,
|
@@ -18,48 +18,125 @@ module Steep
|
|
18
18
|
@index = index
|
19
19
|
end
|
20
20
|
|
21
|
-
def self.
|
21
|
+
def self.start_worker(type, name:, steepfile:, steep_command:, index: nil, delay_shutdown: false, patterns: [])
|
22
|
+
begin
|
23
|
+
unless steep_command
|
24
|
+
fork_worker(
|
25
|
+
type,
|
26
|
+
name: name,
|
27
|
+
steepfile: steepfile,
|
28
|
+
index: index,
|
29
|
+
delay_shutdown: delay_shutdown,
|
30
|
+
patterns: patterns
|
31
|
+
)
|
32
|
+
else
|
33
|
+
# Use `#spawn_worker`
|
34
|
+
raise NotImplementedError
|
35
|
+
end
|
36
|
+
rescue NotImplementedError
|
37
|
+
spawn_worker(
|
38
|
+
type,
|
39
|
+
name: name,
|
40
|
+
steepfile: steepfile,
|
41
|
+
steep_command: steep_command || "steep",
|
42
|
+
index: index,
|
43
|
+
delay_shutdown: delay_shutdown,
|
44
|
+
patterns: patterns
|
45
|
+
)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.fork_worker(type, name:, steepfile:, index:, delay_shutdown:, patterns:)
|
50
|
+
stdin_in, stdin_out = IO.pipe
|
51
|
+
stdout_in, stdout_out = IO.pipe
|
52
|
+
|
53
|
+
worker = Drivers::Worker.new(stdout: stdout_out, stdin: stdin_in, stderr: STDERR)
|
54
|
+
|
55
|
+
worker.steepfile = steepfile
|
56
|
+
worker.worker_type = type
|
57
|
+
worker.worker_name = name
|
58
|
+
worker.delay_shutdown = delay_shutdown
|
59
|
+
if (max, this = index)
|
60
|
+
worker.max_index = max
|
61
|
+
worker.index = this
|
62
|
+
end
|
63
|
+
worker.commandline_args = patterns
|
64
|
+
|
65
|
+
pid = fork do
|
66
|
+
worker.run()
|
67
|
+
end
|
68
|
+
|
69
|
+
pid or raise
|
70
|
+
|
71
|
+
writer = LanguageServer::Protocol::Transport::Io::Writer.new(stdin_out)
|
72
|
+
reader = LanguageServer::Protocol::Transport::Io::Reader.new(stdout_in)
|
73
|
+
|
74
|
+
# @type var wait_thread: Thread & _ProcessWaitThread
|
75
|
+
wait_thread = _ = Thread.new { Process.waitpid(pid) }
|
76
|
+
wait_thread.define_singleton_method(:pid) { pid }
|
77
|
+
|
78
|
+
stdin_in.close
|
79
|
+
stdout_out.close
|
80
|
+
|
81
|
+
new(
|
82
|
+
reader: reader,
|
83
|
+
writer: writer,
|
84
|
+
stderr: STDERR,
|
85
|
+
wait_thread: wait_thread,
|
86
|
+
name: name,
|
87
|
+
index: index&.[](1)
|
88
|
+
)
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.spawn_worker(type, name:, steepfile:, steep_command:, index:, delay_shutdown:, patterns:)
|
22
92
|
args = ["--name=#{name}", "--steepfile=#{steepfile}"]
|
23
93
|
args << (%w(debug info warn error fatal unknown)[Steep.logger.level].yield_self {|log_level| "--log-level=#{log_level}" })
|
94
|
+
|
24
95
|
if Steep.log_output.is_a?(String)
|
25
96
|
args << "--log-output=#{Steep.log_output}"
|
26
97
|
end
|
98
|
+
|
99
|
+
if (max, this = index)
|
100
|
+
args << "--max-index=#{max}"
|
101
|
+
args << "--index=#{this}"
|
102
|
+
end
|
103
|
+
|
104
|
+
if delay_shutdown
|
105
|
+
args << "--delay-shutdown"
|
106
|
+
end
|
107
|
+
|
27
108
|
command = case type
|
28
109
|
when :interaction
|
29
|
-
[steep_command, "worker", "--interaction", *args, *
|
110
|
+
[steep_command, "worker", "--interaction", *args, *patterns]
|
30
111
|
when :typecheck
|
31
|
-
[steep_command, "worker", "--typecheck", *args, *
|
112
|
+
[steep_command, "worker", "--typecheck", *args, *patterns]
|
32
113
|
else
|
33
114
|
raise "Unknown type: #{type}"
|
34
115
|
end
|
35
116
|
|
36
|
-
if delay_shutdown
|
37
|
-
command << "--delay-shutdown"
|
38
|
-
end
|
39
|
-
|
40
117
|
stdin, stdout, thread = if Gem.win_platform?
|
41
|
-
Open3.popen2(*command, new_pgroup: true)
|
118
|
+
__skip__ = Open3.popen2(*command, new_pgroup: true)
|
42
119
|
else
|
43
|
-
Open3.popen2(*command, pgroup: true)
|
120
|
+
__skip__ = Open3.popen2(*command, pgroup: true)
|
44
121
|
end
|
45
122
|
stderr = nil
|
46
123
|
|
47
124
|
writer = LanguageServer::Protocol::Transport::Io::Writer.new(stdin)
|
48
125
|
reader = LanguageServer::Protocol::Transport::Io::Reader.new(stdout)
|
49
126
|
|
50
|
-
new(reader: reader, writer: writer, stderr: stderr, wait_thread: thread, name: name, index: index)
|
127
|
+
new(reader: reader, writer: writer, stderr: stderr, wait_thread: thread, name: name, index: index&.[](1))
|
51
128
|
end
|
52
129
|
|
53
|
-
def self.
|
130
|
+
def self.start_typecheck_workers(steepfile:, args:, steep_command:, count: [Etc.nprocessors - 1, 1].max, delay_shutdown: false)
|
54
131
|
count.times.map do |i|
|
55
|
-
|
132
|
+
start_worker(
|
56
133
|
:typecheck,
|
57
134
|
name: "typecheck@#{i}",
|
58
135
|
steepfile: steepfile,
|
59
136
|
steep_command: steep_command,
|
60
|
-
|
137
|
+
index: [count, i],
|
138
|
+
patterns: args,
|
61
139
|
delay_shutdown: delay_shutdown,
|
62
|
-
index: i
|
63
140
|
)
|
64
141
|
end
|
65
142
|
end
|
@@ -88,7 +88,8 @@ module Steep
|
|
88
88
|
end
|
89
89
|
|
90
90
|
Steep.measure "typechecking" do
|
91
|
-
|
91
|
+
resolver = RBS::Resolver::ConstantResolver.new(builder: subtyping.factory.definition_builder)
|
92
|
+
@typing = TypeCheckService.type_check(source: source, subtyping: subtyping, constant_resolver: resolver)
|
92
93
|
end
|
93
94
|
end
|
94
95
|
|
@@ -211,8 +211,9 @@ module Steep
|
|
211
211
|
subtyping = signature_service.current_subtyping or return
|
212
212
|
source = Source.parse(content, path: path, factory: subtyping.factory)
|
213
213
|
source = source.without_unrelated_defs(line: line, column: column)
|
214
|
+
resolver = RBS::Resolver::ConstantResolver.new(builder: subtyping.factory.definition_builder)
|
214
215
|
[
|
215
|
-
Services::TypeCheckService.type_check(source: source, subtyping: subtyping),
|
216
|
+
Services::TypeCheckService.type_check(source: source, subtyping: subtyping, constant_resolver: resolver),
|
216
217
|
signature_service
|
217
218
|
]
|
218
219
|
rescue
|
@@ -2,9 +2,9 @@ module Steep
|
|
2
2
|
module Services
|
3
3
|
module HoverProvider
|
4
4
|
class RBS
|
5
|
-
TypeAliasContent = Struct.new(:location, :decl, keyword_init: true)
|
6
|
-
ClassContent = Struct.new(:location, :decl, keyword_init: true)
|
7
|
-
InterfaceContent = Struct.new(:location, :decl, keyword_init: true)
|
5
|
+
TypeAliasContent = _ = Struct.new(:location, :decl, keyword_init: true)
|
6
|
+
ClassContent = _ = Struct.new(:location, :decl, keyword_init: true)
|
7
|
+
InterfaceContent = _ = Struct.new(:location, :decl, keyword_init: true)
|
8
8
|
|
9
9
|
attr_reader :service
|
10
10
|
|
@@ -33,14 +33,14 @@ module Steep
|
|
33
33
|
alias_decl = service.latest_env.alias_decls[head.name]&.decl or raise
|
34
34
|
|
35
35
|
TypeAliasContent.new(
|
36
|
-
location: head.location,
|
36
|
+
location: head.location || raise,
|
37
37
|
decl: alias_decl
|
38
38
|
)
|
39
39
|
when ::RBS::Types::ClassInstance, ::RBS::Types::ClassSingleton
|
40
40
|
if loc_key == :name
|
41
41
|
env = service.latest_env
|
42
|
-
class_decl = env.class_decls[head.name]&.decls[0
|
43
|
-
location = head.location[:name
|
42
|
+
class_decl = env.class_decls[head.name]&.decls&.[](0)&.decl or raise
|
43
|
+
location = head.location&.[](:name) or raise
|
44
44
|
ClassContent.new(
|
45
45
|
location: location,
|
46
46
|
decl: class_decl
|
@@ -49,7 +49,7 @@ module Steep
|
|
49
49
|
when ::RBS::Types::Interface
|
50
50
|
env = service.latest_env
|
51
51
|
interface_decl = env.interface_decls[head.name]&.decl or raise
|
52
|
-
location = head.location[:name
|
52
|
+
location = head.location&.[](:name) or raise
|
53
53
|
|
54
54
|
InterfaceContent.new(
|
55
55
|
location: location,
|
@@ -4,6 +4,7 @@ module Steep
|
|
4
4
|
class Ruby
|
5
5
|
TypeContent = _ = Struct.new(:node, :type, :location, keyword_init: true)
|
6
6
|
VariableContent = _ = Struct.new(:node, :name, :type, :location, keyword_init: true)
|
7
|
+
TypeAssertionContent = _ = Struct.new(:node, :original_type, :asserted_type, :location, keyword_init: true)
|
7
8
|
MethodCallContent = _ = Struct.new(:node, :method_call, :location, keyword_init: true)
|
8
9
|
DefinitionContent = _ = Struct.new(:node, :method_name, :method_type, :definition, :location, keyword_init: true)
|
9
10
|
ConstantContent = _ = Struct.new(:location, :full_name, :type, :decl, keyword_init: true) do
|
@@ -33,11 +34,15 @@ module Steep
|
|
33
34
|
end
|
34
35
|
|
35
36
|
def constant?
|
36
|
-
decl.is_a?(::RBS::Environment::SingleEntry)
|
37
|
+
if decl.is_a?(::RBS::Environment::SingleEntry)
|
38
|
+
decl
|
39
|
+
end
|
37
40
|
end
|
38
41
|
|
39
42
|
def class_or_module?
|
40
|
-
decl.is_a?(::RBS::Environment::MultiEntry)
|
43
|
+
if decl.is_a?(::RBS::Environment::MultiEntry)
|
44
|
+
decl
|
45
|
+
end
|
41
46
|
end
|
42
47
|
end
|
43
48
|
|
@@ -72,14 +77,16 @@ module Steep
|
|
72
77
|
subtyping = service.signature_services[target.name].current_subtyping or return
|
73
78
|
source = Source.parse(content, path: path, factory: subtyping.factory)
|
74
79
|
source = source.without_unrelated_defs(line: line, column: column)
|
75
|
-
|
80
|
+
resolver = ::RBS::Resolver::ConstantResolver.new(builder: subtyping.factory.definition_builder)
|
81
|
+
Services::TypeCheckService.type_check(source: source, subtyping: subtyping, constant_resolver: resolver)
|
76
82
|
rescue
|
77
83
|
nil
|
78
84
|
end
|
79
85
|
|
80
86
|
def method_name_from_method(context, builder:)
|
81
|
-
|
82
|
-
|
87
|
+
context.method or raise
|
88
|
+
defined_in = context.method.defined_in or raise
|
89
|
+
method_name = context.name or raise
|
83
90
|
|
84
91
|
case
|
85
92
|
when defined_in.class?
|
@@ -171,6 +178,15 @@ module Steep
|
|
171
178
|
decl: decl
|
172
179
|
)
|
173
180
|
end
|
181
|
+
when :assertion
|
182
|
+
original_node, _ = node.children
|
183
|
+
|
184
|
+
original_type = typing.type_of(node: original_node)
|
185
|
+
asserted_type = typing.type_of(node: node)
|
186
|
+
|
187
|
+
if original_type != asserted_type
|
188
|
+
return TypeAssertionContent.new(node: node, original_type: original_type, asserted_type: asserted_type, location: node.location.expression)
|
189
|
+
end
|
174
190
|
end
|
175
191
|
|
176
192
|
TypeContent.new(
|
@@ -19,6 +19,10 @@ module Steep
|
|
19
19
|
builder.env(last_builder.env)
|
20
20
|
end
|
21
21
|
end
|
22
|
+
|
23
|
+
def constant_resolver
|
24
|
+
@constant_resolver ||= RBS::Resolver::ConstantResolver.new(builder: last_builder)
|
25
|
+
end
|
22
26
|
end
|
23
27
|
|
24
28
|
class AncestorErrorStatus
|
@@ -37,6 +41,10 @@ module Steep
|
|
37
41
|
builder.env(last_builder.env)
|
38
42
|
end
|
39
43
|
end
|
44
|
+
|
45
|
+
def constant_resolver
|
46
|
+
@constant_resolver ||= RBS::Resolver::ConstantResolver.new(builder: last_builder)
|
47
|
+
end
|
40
48
|
end
|
41
49
|
|
42
50
|
class LoadedStatus
|
@@ -61,6 +69,10 @@ module Steep
|
|
61
69
|
builder.env(self.builder.env)
|
62
70
|
end
|
63
71
|
end
|
72
|
+
|
73
|
+
def constant_resolver
|
74
|
+
@constant_resolver ||= RBS::Resolver::ConstantResolver.new(builder: builder)
|
75
|
+
end
|
64
76
|
end
|
65
77
|
|
66
78
|
FileStatus = _ = Struct.new(:path, :content, :decls, keyword_init: true)
|
@@ -125,6 +137,10 @@ module Steep
|
|
125
137
|
status.rbs_index
|
126
138
|
end
|
127
139
|
|
140
|
+
def latest_constant_resolver
|
141
|
+
status.constant_resolver
|
142
|
+
end
|
143
|
+
|
128
144
|
def current_subtyping
|
129
145
|
if status.is_a?(LoadedStatus)
|
130
146
|
status.subtyping
|
@@ -174,7 +190,7 @@ module Steep
|
|
174
190
|
file.decls
|
175
191
|
else
|
176
192
|
# factory is not used here because the error is a syntax error.
|
177
|
-
Diagnostic::Signature.from_rbs_error(file.decls, factory: nil)
|
193
|
+
Diagnostic::Signature.from_rbs_error(file.decls, factory: _ = nil)
|
178
194
|
end
|
179
195
|
diagnostics << diagnostic
|
180
196
|
end
|
@@ -214,6 +230,7 @@ module Steep
|
|
214
230
|
|
215
231
|
def update_env(updated_files, paths:)
|
216
232
|
Steep.logger.tagged "#update_env" do
|
233
|
+
# @type var errors: Array[RBS::BaseError]
|
217
234
|
errors = []
|
218
235
|
new_decls = Set[].compare_by_identity
|
219
236
|
|
@@ -230,7 +247,9 @@ module Steep
|
|
230
247
|
updated_files.each_value do |content|
|
231
248
|
case decls = content.decls
|
232
249
|
when RBS::BaseError
|
233
|
-
errors <<
|
250
|
+
errors << decls
|
251
|
+
when Diagnostic::Signature::UnexpectedError
|
252
|
+
return [decls]
|
234
253
|
else
|
235
254
|
begin
|
236
255
|
decls.each do |decl|
|
@@ -255,7 +274,7 @@ module Steep
|
|
255
274
|
unless errors.empty?
|
256
275
|
return errors.map {|error|
|
257
276
|
# Factory will not be used because of the possible error types.
|
258
|
-
Diagnostic::Signature.from_rbs_error(error, factory: nil)
|
277
|
+
Diagnostic::Signature.from_rbs_error(error, factory: _ = nil)
|
259
278
|
}
|
260
279
|
end
|
261
280
|
|
@@ -277,7 +296,7 @@ module Steep
|
|
277
296
|
|
278
297
|
unless errors.empty?
|
279
298
|
# Builder won't be used.
|
280
|
-
factory = AST::Types::Factory.new(builder: nil)
|
299
|
+
factory = AST::Types::Factory.new(builder: _ = nil)
|
281
300
|
return errors.map {|error| Diagnostic::Signature.from_rbs_error(error, factory: factory) }
|
282
301
|
end
|
283
302
|
|
@@ -280,7 +280,7 @@ module Steep
|
|
280
280
|
|
281
281
|
if subtyping
|
282
282
|
text = source_files[path].content
|
283
|
-
file = type_check_file(target: target, subtyping: subtyping, path: path, text: text)
|
283
|
+
file = type_check_file(target: target, subtyping: subtyping, path: path, text: text) { signature_service.latest_constant_resolver }
|
284
284
|
yield [file.path, file.diagnostics]
|
285
285
|
source_files[path] = file
|
286
286
|
end
|
@@ -326,7 +326,7 @@ module Steep
|
|
326
326
|
def type_check_file(target:, subtyping:, path:, text:)
|
327
327
|
Steep.logger.tagged "#type_check_file(#{path}@#{target.name})" do
|
328
328
|
source = Source.parse(text, path: path, factory: subtyping.factory)
|
329
|
-
typing = TypeCheckService.type_check(source: source, subtyping: subtyping)
|
329
|
+
typing = TypeCheckService.type_check(source: source, subtyping: subtyping, constant_resolver: yield)
|
330
330
|
SourceFile.with_typing(path: path, content: text, node: source.node, typing: typing)
|
331
331
|
end
|
332
332
|
rescue AnnotationParser::SyntaxError => exn
|
@@ -342,7 +342,7 @@ module Steep
|
|
342
342
|
SourceFile.no_data(path: path, content: text)
|
343
343
|
end
|
344
344
|
|
345
|
-
def self.type_check(source:, subtyping:)
|
345
|
+
def self.type_check(source:, subtyping:, constant_resolver:)
|
346
346
|
annotations = source.annotations(block: source.node, factory: subtyping.factory, context: nil)
|
347
347
|
|
348
348
|
definition = subtyping.factory.definition_builder.build_instance(AST::Builtin::Object.module_name)
|
@@ -350,7 +350,7 @@ module Steep
|
|
350
350
|
const_env = TypeInference::ConstantEnv.new(
|
351
351
|
factory: subtyping.factory,
|
352
352
|
context: nil,
|
353
|
-
resolver:
|
353
|
+
resolver: constant_resolver
|
354
354
|
)
|
355
355
|
type_env = TypeInference::TypeEnv.new(const_env)
|
356
356
|
type_env = TypeInference::TypeEnvBuilder.new(
|