steep 1.2.1 → 1.3.0.pre.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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(
|