steep 1.8.0.dev.1 → 1.8.0.pre.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +33 -0
- data/README.md +3 -2
- data/bin/mem_graph.rb +67 -0
- data/bin/mem_prof.rb +102 -0
- data/bin/stackprof_test.rb +19 -0
- data/bin/steep-check.rb +251 -0
- data/guides/src/gem-rbs-collection/gem-rbs-collection.md +1 -1
- data/lib/steep/annotation_parser.rb +1 -1
- data/lib/steep/ast/builtin.rb +5 -5
- data/lib/steep/ast/node/type_application.rb +7 -6
- data/lib/steep/ast/types/any.rb +1 -9
- data/lib/steep/ast/types/boolean.rb +8 -16
- data/lib/steep/ast/types/bot.rb +2 -10
- data/lib/steep/ast/types/class.rb +1 -13
- data/lib/steep/ast/types/factory.rb +101 -85
- data/lib/steep/ast/types/instance.rb +1 -13
- data/lib/steep/ast/types/intersection.rb +8 -15
- data/lib/steep/ast/types/literal.rb +2 -8
- data/lib/steep/ast/types/logic.rb +3 -24
- data/lib/steep/ast/types/name.rb +5 -16
- data/lib/steep/ast/types/nil.rb +3 -12
- data/lib/steep/ast/types/proc.rb +4 -13
- data/lib/steep/ast/types/record.rb +21 -12
- data/lib/steep/ast/types/self.rb +1 -13
- data/lib/steep/ast/types/shared_instance.rb +11 -0
- data/lib/steep/ast/types/top.rb +1 -9
- data/lib/steep/ast/types/tuple.rb +4 -10
- data/lib/steep/ast/types/union.rb +10 -15
- data/lib/steep/ast/types/var.rb +4 -13
- data/lib/steep/ast/types/void.rb +2 -10
- data/lib/steep/diagnostic/ruby.rb +10 -10
- data/lib/steep/drivers/check.rb +11 -14
- data/lib/steep/drivers/checkfile.rb +8 -10
- data/lib/steep/drivers/stats.rb +17 -13
- data/lib/steep/drivers/utils/driver_helper.rb +24 -3
- data/lib/steep/drivers/watch.rb +3 -3
- data/lib/steep/interface/builder.rb +162 -138
- data/lib/steep/interface/method_type.rb +12 -20
- data/lib/steep/interface/shape.rb +66 -10
- data/lib/steep/interface/substitution.rb +2 -0
- data/lib/steep/interface/type_param.rb +20 -7
- data/lib/steep/located_value.rb +20 -0
- data/lib/steep/server/change_buffer.rb +5 -7
- data/lib/steep/server/custom_methods.rb +61 -0
- data/lib/steep/server/delay_queue.rb +8 -1
- data/lib/steep/server/interaction_worker.rb +13 -6
- data/lib/steep/server/lsp_formatter.rb +8 -6
- data/lib/steep/server/master.rb +195 -142
- data/lib/steep/server/type_check_worker.rb +25 -22
- data/lib/steep/server/work_done_progress.rb +64 -0
- data/lib/steep/server/worker_process.rb +1 -1
- data/lib/steep/services/completion_provider.rb +32 -24
- data/lib/steep/services/goto_service.rb +3 -2
- data/lib/steep/services/hover_provider/ruby.rb +30 -17
- data/lib/steep/services/signature_help_provider.rb +9 -7
- data/lib/steep/services/signature_service.rb +1 -1
- data/lib/steep/services/type_check_service.rb +19 -9
- data/lib/steep/signature/validator.rb +17 -20
- data/lib/steep/source.rb +47 -1
- data/lib/steep/subtyping/check.rb +105 -55
- data/lib/steep/subtyping/constraints.rb +13 -17
- data/lib/steep/type_construction.rb +106 -100
- data/lib/steep/type_inference/block_params.rb +8 -5
- data/lib/steep/type_inference/logic_type_interpreter.rb +11 -7
- data/lib/steep/type_inference/method_call.rb +3 -3
- data/lib/steep/type_inference/method_params.rb +1 -1
- data/lib/steep/type_inference/send_args.rb +1 -1
- data/lib/steep/typing.rb +164 -106
- data/lib/steep/version.rb +1 -1
- data/lib/steep.rb +29 -4
- data/steep.gemspec +2 -2
- metadata +16 -9
- data/lib/steep/type_inference/context_array.rb +0 -112
@@ -11,9 +11,7 @@ module Steep
|
|
11
11
|
TypeCheckCodeJob = _ = Struct.new(:guid, :path, keyword_init: true)
|
12
12
|
ValidateAppSignatureJob = _ = Struct.new(:guid, :path, keyword_init: true)
|
13
13
|
ValidateLibrarySignatureJob = _ = Struct.new(:guid, :path, keyword_init: true)
|
14
|
-
GotoJob
|
15
|
-
# @implements GotoJob
|
16
|
-
|
14
|
+
class GotoJob < Struct.new(:id, :kind, :params, keyword_init: true)
|
17
15
|
def self.implementation(id:, params:)
|
18
16
|
new(
|
19
17
|
kind: :implementation,
|
@@ -57,7 +55,6 @@ module Steep
|
|
57
55
|
super(project: project, reader: reader, writer: writer)
|
58
56
|
|
59
57
|
@assignment = assignment
|
60
|
-
@service = Services::TypeCheckService.new(project: project)
|
61
58
|
@buffered_changes = {}
|
62
59
|
@mutex = Mutex.new()
|
63
60
|
@queue = Queue.new
|
@@ -65,30 +62,35 @@ module Steep
|
|
65
62
|
@current_type_check_guid = nil
|
66
63
|
end
|
67
64
|
|
65
|
+
def service
|
66
|
+
@service ||= Services::TypeCheckService.new(project: project)
|
67
|
+
end
|
68
|
+
|
68
69
|
def handle_request(request)
|
69
70
|
case request[:method]
|
70
71
|
when "initialize"
|
71
|
-
load_files(project: project, commandline_args: commandline_args)
|
72
72
|
writer.write({ id: request[:id], result: nil})
|
73
73
|
|
74
74
|
when "textDocument/didChange"
|
75
75
|
collect_changes(request)
|
76
76
|
|
77
|
-
when
|
78
|
-
|
79
|
-
|
77
|
+
when CustomMethods::FileLoad::METHOD
|
78
|
+
input = request[:params][:content]
|
79
|
+
load_files(input)
|
80
|
+
|
81
|
+
when CustomMethods::FileReset::METHOD
|
82
|
+
params = request[:params] #: CustomMethods::FileReset::params
|
83
|
+
uri = params[:uri]
|
84
|
+
text = params[:content]
|
80
85
|
reset_change(uri: uri, text: text)
|
81
86
|
|
82
87
|
when "workspace/symbol"
|
83
88
|
query = request[:params][:query]
|
84
89
|
queue << WorkspaceSymbolJob.new(id: request[:id], query: query)
|
85
|
-
when
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
end
|
90
|
-
when "$/typecheck/start"
|
91
|
-
params = request[:params]
|
90
|
+
when CustomMethods::Stats::METHOD
|
91
|
+
queue << StatsJob.new(id: request[:id])
|
92
|
+
when CustomMethods::TypeCheck__Start::METHOD
|
93
|
+
params = request[:params] #: CustomMethods::TypeCheck__Start::params
|
92
94
|
enqueue_typecheck_jobs(params)
|
93
95
|
when "textDocument/definition"
|
94
96
|
queue << GotoJob.definition(id: request[:id], params: request[:params])
|
@@ -173,7 +175,9 @@ module Steep
|
|
173
175
|
method: :"textDocument/publishDiagnostics",
|
174
176
|
params: LSP::Interface::PublishDiagnosticsParams.new(
|
175
177
|
uri: Steep::PathHelper.to_uri(job.path).to_s,
|
176
|
-
diagnostics: diagnostics.map {|diagnostic|
|
178
|
+
diagnostics: diagnostics.map {|diagnostic|
|
179
|
+
_ = formatter.format(diagnostic)
|
180
|
+
}.uniq
|
177
181
|
)
|
178
182
|
)
|
179
183
|
end
|
@@ -191,7 +195,7 @@ module Steep
|
|
191
195
|
method: :"textDocument/publishDiagnostics",
|
192
196
|
params: LSP::Interface::PublishDiagnosticsParams.new(
|
193
197
|
uri: Steep::PathHelper.to_uri(job.path).to_s,
|
194
|
-
diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq.compact
|
198
|
+
diagnostics: diagnostics.map {|diagnostic| _ = formatter.format(diagnostic) }.uniq.compact
|
195
199
|
)
|
196
200
|
)
|
197
201
|
end
|
@@ -210,7 +214,9 @@ module Steep
|
|
210
214
|
method: :"textDocument/publishDiagnostics",
|
211
215
|
params: LSP::Interface::PublishDiagnosticsParams.new(
|
212
216
|
uri: Steep::PathHelper.to_uri(job.path).to_s,
|
213
|
-
diagnostics: diagnostics.map {|diagnostic|
|
217
|
+
diagnostics: diagnostics.map {|diagnostic|
|
218
|
+
_ = formatter.format(diagnostic)
|
219
|
+
}.uniq.compact
|
214
220
|
)
|
215
221
|
)
|
216
222
|
end
|
@@ -237,10 +243,7 @@ module Steep
|
|
237
243
|
end
|
238
244
|
|
239
245
|
def typecheck_progress(guid:, path:)
|
240
|
-
writer.write(
|
241
|
-
method: "$/typecheck/progress",
|
242
|
-
params: { guid: guid, path: path }
|
243
|
-
)
|
246
|
+
writer.write(CustomMethods::TypeCheck__Progress.notification({ guid: guid, path: path.to_s }))
|
244
247
|
end
|
245
248
|
|
246
249
|
def workspace_symbol_result(query)
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Steep
|
2
|
+
module Server
|
3
|
+
class WorkDoneProgress
|
4
|
+
attr_reader :sender, :guid, :percentage
|
5
|
+
|
6
|
+
def initialize(guid, &block)
|
7
|
+
@sender = block
|
8
|
+
@guid = guid
|
9
|
+
@percentage = 0
|
10
|
+
end
|
11
|
+
|
12
|
+
def begin(title, message = nil, request_id:)
|
13
|
+
sender.call(
|
14
|
+
{
|
15
|
+
id: request_id,
|
16
|
+
method: "window/workDoneProgress/create",
|
17
|
+
params: { token: guid }
|
18
|
+
}
|
19
|
+
)
|
20
|
+
|
21
|
+
value = { kind: "begin", cancellable: false, title: title, percentage: percentage }
|
22
|
+
value[:message] = message if message
|
23
|
+
|
24
|
+
sender.call(
|
25
|
+
{
|
26
|
+
method: "$/progress",
|
27
|
+
params: { token: guid, value: value }
|
28
|
+
}
|
29
|
+
)
|
30
|
+
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
def report(percentage, message = nil)
|
35
|
+
@percentage = percentage
|
36
|
+
value = { kind: "report", percentage: percentage }
|
37
|
+
value[:message] = message if message
|
38
|
+
|
39
|
+
sender.call(
|
40
|
+
{
|
41
|
+
method: "$/progress",
|
42
|
+
params: { token: guid, value: value }
|
43
|
+
}
|
44
|
+
)
|
45
|
+
|
46
|
+
self
|
47
|
+
end
|
48
|
+
|
49
|
+
def end(message = nil)
|
50
|
+
value = { kind: "end" }
|
51
|
+
value[:message] = message if message
|
52
|
+
|
53
|
+
sender.call(
|
54
|
+
{
|
55
|
+
method: "$/progress",
|
56
|
+
params: { token: guid, value: value }
|
57
|
+
}
|
58
|
+
)
|
59
|
+
|
60
|
+
self
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -132,7 +132,7 @@ module Steep
|
|
132
132
|
new(reader: reader, writer: writer, stderr: stderr, wait_thread: thread, name: name, index: index&.[](1))
|
133
133
|
end
|
134
134
|
|
135
|
-
def self.start_typecheck_workers(steepfile:, args:, steep_command:, count: [Etc.nprocessors - 1, 1].max, delay_shutdown: false)
|
135
|
+
def self.start_typecheck_workers(steepfile:, args:, steep_command:, count: [Etc.nprocessors - 1, 1].max || raise, delay_shutdown: false)
|
136
136
|
count.times.map do |i|
|
137
137
|
start_worker(
|
138
138
|
:typecheck,
|
@@ -183,8 +183,9 @@ module Steep
|
|
183
183
|
end
|
184
184
|
|
185
185
|
Steep.measure "typechecking" do
|
186
|
+
location = source.buffer.loc_to_pos([line, column])
|
186
187
|
resolver = RBS::Resolver::ConstantResolver.new(builder: subtyping.factory.definition_builder)
|
187
|
-
@typing = TypeCheckService.type_check(source: source, subtyping: subtyping, constant_resolver: resolver)
|
188
|
+
@typing = TypeCheckService.type_check(source: source, subtyping: subtyping, constant_resolver: resolver, cursor: location)
|
188
189
|
end
|
189
190
|
end
|
190
191
|
|
@@ -348,7 +349,7 @@ module Steep
|
|
348
349
|
|
349
350
|
items = [] #: Array[item]
|
350
351
|
|
351
|
-
context = typing.
|
352
|
+
context = typing.cursor_context.context or raise
|
352
353
|
|
353
354
|
case
|
354
355
|
when node.type == :send && node.children[0] == nil && at_end?(position, of: (_ = node.loc).selector)
|
@@ -469,7 +470,7 @@ module Steep
|
|
469
470
|
|
470
471
|
if at_end?(shift_pos, of: node.loc)
|
471
472
|
begin
|
472
|
-
context = typing.
|
473
|
+
context = typing.cursor_context.context or raise
|
473
474
|
receiver_type =
|
474
475
|
case (type = typing.type_of(node: node))
|
475
476
|
when AST::Types::Self
|
@@ -499,7 +500,7 @@ module Steep
|
|
499
500
|
|
500
501
|
if at_end?(shift_pos, of: node.loc)
|
501
502
|
begin
|
502
|
-
context = typing.
|
503
|
+
context = typing.cursor_context.context or raise
|
503
504
|
receiver_type =
|
504
505
|
case (type = typing.type_of(node: node))
|
505
506
|
when AST::Types::Self
|
@@ -529,11 +530,11 @@ module Steep
|
|
529
530
|
case node&.type
|
530
531
|
when :const
|
531
532
|
# Constant:: ←
|
532
|
-
context = typing.
|
533
|
+
context = typing.cursor_context.context or raise
|
533
534
|
constant_items_for_context(context, parent: node, position: position, items: items, prefix: "")
|
534
535
|
when nil
|
535
536
|
# :: ←
|
536
|
-
context = typing.
|
537
|
+
context = typing.cursor_context.context or raise
|
537
538
|
constant_items_for_context(context, parent: nil, position: position, items: items, prefix: "")
|
538
539
|
end
|
539
540
|
|
@@ -552,7 +553,7 @@ module Steep
|
|
552
553
|
|
553
554
|
return [] unless node
|
554
555
|
|
555
|
-
context = typing.
|
556
|
+
context = typing.cursor_context.context or raise
|
556
557
|
items = [] #: Array[item]
|
557
558
|
instance_variable_items_for_context(context, prefix: "@", position: position, items: items)
|
558
559
|
items
|
@@ -561,7 +562,7 @@ module Steep
|
|
561
562
|
def items_for_rbs(position:, buffer:)
|
562
563
|
items = [] #: Array[item]
|
563
564
|
|
564
|
-
context = typing.
|
565
|
+
context = typing.cursor_context.context or raise
|
565
566
|
completion = TypeNameCompletion.new(env: context.env, context: context.module_context.nesting, dirs: [])
|
566
567
|
prefix = TypeNameCompletion::Prefix.parse(buffer, line: position.line, column: position.column)
|
567
568
|
|
@@ -609,7 +610,7 @@ module Steep
|
|
609
610
|
|
610
611
|
def method_items_for_receiver_type(type, include_private:, prefix:, position:, items:)
|
611
612
|
range = range_for(position, prefix: prefix)
|
612
|
-
context = typing.
|
613
|
+
context = typing.cursor_context.context or raise
|
613
614
|
|
614
615
|
config =
|
615
616
|
if (module_type = context.module_context&.module_type) && (instance_type = context.module_context&.instance_type)
|
@@ -634,39 +635,40 @@ module Steep
|
|
634
635
|
case type
|
635
636
|
when AST::Types::Name::Instance, AST::Types::Name::Interface, AST::Types::Name::Singleton
|
636
637
|
# Simple method type
|
637
|
-
all_decls = Set.new(method_entry.
|
638
|
+
all_decls = Set.new(method_entry.overloads.flat_map {|overload| overload.method_decls(name) }).sort_by {|decl| decl.method_name.to_s }
|
638
639
|
all_members = Set.new(all_decls.flat_map {|decl| decl.method_def.member })
|
639
640
|
all_members.each do |member|
|
640
641
|
associated_decl = all_decls.find {|decl| decl.method_def.member == member } or next
|
641
|
-
|
642
|
+
overloads = method_entry.overloads.select {|overload| overload.method_defs.any? {|defn| defn.member == member }}
|
642
643
|
items << SimpleMethodNameItem.new(
|
643
644
|
identifier: name,
|
644
645
|
range: range,
|
645
646
|
receiver_type: type,
|
646
647
|
method_name: associated_decl.method_name,
|
647
|
-
method_types:
|
648
|
+
method_types: overloads.map {|overload| subtyping.factory.method_type_1(overload.method_type) },
|
648
649
|
method_member: member
|
649
650
|
)
|
650
651
|
end
|
651
652
|
else
|
652
|
-
|
653
|
+
generated_overloads, defined_overloads =
|
654
|
+
method_entry.overloads.partition {|overload| overload.method_defs.empty? }
|
653
655
|
|
654
|
-
unless
|
656
|
+
unless defined_overloads.empty?
|
655
657
|
items << ComplexMethodNameItem.new(
|
656
658
|
identifier: name,
|
657
659
|
range: range,
|
658
660
|
receiver_type: type,
|
659
|
-
method_types:
|
660
|
-
method_decls:
|
661
|
+
method_types: defined_overloads.map { subtyping.factory.method_type_1(_1.method_type) },
|
662
|
+
method_decls: defined_overloads.flat_map { _1.method_decls(name).to_a }.sort_by {|decl| decl.method_name.to_s }
|
661
663
|
)
|
662
664
|
end
|
663
665
|
|
664
|
-
unless
|
666
|
+
unless generated_overloads.empty?
|
665
667
|
items << GeneratedMethodNameItem.new(
|
666
668
|
identifier: name,
|
667
669
|
range: range,
|
668
670
|
receiver_type: type,
|
669
|
-
method_types:
|
671
|
+
method_types: generated_overloads.map { subtyping.factory.method_type_1(_1.method_type) }
|
670
672
|
)
|
671
673
|
end
|
672
674
|
end
|
@@ -725,27 +727,33 @@ module Steep
|
|
725
727
|
end
|
726
728
|
|
727
729
|
def keyword_argument_items_for_method(call_node:, send_node:, position:, prefix:, items:)
|
728
|
-
|
730
|
+
_receiver_node, _method_name, argument_nodes = deconstruct_send_node!(send_node)
|
729
731
|
|
730
732
|
call = typing.call_of(node: call_node)
|
731
733
|
|
732
734
|
case call
|
733
735
|
when TypeInference::MethodCall::Typed, TypeInference::MethodCall::Error
|
734
|
-
context = typing.
|
736
|
+
context = typing.cursor_context.context or raise
|
735
737
|
type = call.receiver_type
|
738
|
+
type = type.subst(Interface::Substitution.build([], self_type: context.self_type, module_type: context.module_context&.module_type, instance_type: context.module_context&.instance_type))
|
736
739
|
|
737
740
|
config = Interface::Builder::Config.new(self_type: type, variable_bounds: context.variable_context.upper_bounds)
|
738
741
|
if shape = subtyping.builder.shape(type, config)
|
739
742
|
shape = shape.public_shape if private_send?(call_node)
|
740
743
|
if method = shape.methods[call.method_name]
|
741
|
-
method.
|
742
|
-
defn =
|
744
|
+
method.overloads.each.with_index do |overload, i|
|
745
|
+
defn = overload.method_decls(call.method_name).to_a[0]&.method_def
|
743
746
|
if defn && defn.type.type
|
744
747
|
range = range_for(position, prefix: prefix)
|
745
748
|
kwargs = argument_nodes.find { |arg| arg.type == :kwargs }&.children || []
|
746
749
|
used_kwargs = kwargs.filter_map { |arg| arg.type == :pair && arg.children.first.children.first }
|
747
750
|
|
748
|
-
|
751
|
+
if defn.type.type.is_a?(RBS::Types::UntypedFunction)
|
752
|
+
kwargs = [] #: Array[Symbol]
|
753
|
+
else
|
754
|
+
kwargs = defn.type.type.required_keywords.keys + defn.type.type.optional_keywords.keys
|
755
|
+
end
|
756
|
+
|
749
757
|
kwargs.each do |name|
|
750
758
|
if name.to_s.start_with?(prefix) && !used_kwargs.include?(name)
|
751
759
|
items << KeywordArgumentItem.new(identifier: "#{name}:", range: range)
|
@@ -784,7 +792,7 @@ module Steep
|
|
784
792
|
def unwrap_optional(type)
|
785
793
|
if type.is_a?(AST::Types::Union) && type.types.include?(AST::Builtin.nil_type)
|
786
794
|
types = type.types.reject { |t| t == AST::Builtin.nil_type }
|
787
|
-
AST::Types::Union.new(types: types
|
795
|
+
AST::Types::Union.new(types: types)
|
788
796
|
else
|
789
797
|
type
|
790
798
|
end
|
@@ -176,7 +176,7 @@ module Steep
|
|
176
176
|
when :def, :defs
|
177
177
|
named_location = (_ = node.location) #: Parser::AST::_NamedLocation
|
178
178
|
if test_ast_location(named_location.name, line: line, column: column)
|
179
|
-
if method_context = typing.
|
179
|
+
if method_context = typing.cursor_context.context&.method_context
|
180
180
|
if method = method_context.method
|
181
181
|
method.defs.each do |defn|
|
182
182
|
singleton_method =
|
@@ -285,8 +285,9 @@ module Steep
|
|
285
285
|
source = Source.parse(content, path: path, factory: subtyping.factory)
|
286
286
|
source = source.without_unrelated_defs(line: line, column: column)
|
287
287
|
resolver = RBS::Resolver::ConstantResolver.new(builder: subtyping.factory.definition_builder)
|
288
|
+
loc = source.buffer.loc_to_pos([line, column])
|
288
289
|
[
|
289
|
-
Services::TypeCheckService.type_check(source: source, subtyping: subtyping, constant_resolver: resolver),
|
290
|
+
Services::TypeCheckService.type_check(source: source, subtyping: subtyping, constant_resolver: resolver, cursor: loc),
|
290
291
|
signature_service
|
291
292
|
]
|
292
293
|
rescue
|
@@ -84,7 +84,8 @@ module Steep
|
|
84
84
|
source = Source.parse(content, path: path, factory: subtyping.factory)
|
85
85
|
source = source.without_unrelated_defs(line: line, column: column)
|
86
86
|
resolver = ::RBS::Resolver::ConstantResolver.new(builder: subtyping.factory.definition_builder)
|
87
|
-
|
87
|
+
pos = source.buffer.loc_to_pos([line, column])
|
88
|
+
Services::TypeCheckService.type_check(source: source, subtyping: subtyping, constant_resolver: resolver, cursor: pos)
|
88
89
|
rescue
|
89
90
|
nil
|
90
91
|
end
|
@@ -118,17 +119,27 @@ module Steep
|
|
118
119
|
case node.type
|
119
120
|
when :lvar
|
120
121
|
var_name = node.children[0]
|
121
|
-
context = typing.
|
122
|
-
var_type = context.type_env[var_name] || AST::Types::Any.
|
122
|
+
context = typing.cursor_context.context or raise
|
123
|
+
var_type = context.type_env[var_name] || AST::Types::Any.instance()
|
123
124
|
|
124
|
-
return VariableContent.new(
|
125
|
+
return VariableContent.new(
|
126
|
+
node: node,
|
127
|
+
name: var_name,
|
128
|
+
type: var_type,
|
129
|
+
location: node.location.name # steep:ignore NoMethod
|
130
|
+
)
|
125
131
|
|
126
132
|
when :lvasgn
|
127
133
|
var_name, rhs = node.children
|
128
|
-
context = typing.
|
134
|
+
context = typing.cursor_context.context or raise
|
129
135
|
type = context.type_env[var_name] || typing.type_of(node: node)
|
130
136
|
|
131
|
-
return VariableContent.new(
|
137
|
+
return VariableContent.new(
|
138
|
+
node: node,
|
139
|
+
name: var_name,
|
140
|
+
type: type,
|
141
|
+
location: node.location.name # steep:ignore NoMethod
|
142
|
+
)
|
132
143
|
|
133
144
|
when :send, :csend
|
134
145
|
result_node =
|
@@ -149,27 +160,29 @@ module Steep
|
|
149
160
|
return MethodCallContent.new(
|
150
161
|
node: result_node,
|
151
162
|
method_call: call,
|
152
|
-
location: node.location.selector
|
163
|
+
location: node.location.selector # steep:ignore NoMethod
|
153
164
|
)
|
154
165
|
end
|
155
166
|
end
|
156
167
|
|
157
168
|
when :def, :defs
|
158
|
-
context = typing.
|
169
|
+
context = typing.cursor_context.context or raise
|
159
170
|
method_context = context.method_context
|
160
171
|
|
161
172
|
if method_context && method_context.method
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
173
|
+
if method_context.method_type
|
174
|
+
return DefinitionContent.new(
|
175
|
+
node: node,
|
176
|
+
method_name: method_name_from_method(method_context, builder: context.factory.definition_builder),
|
177
|
+
method_type: method_context.method_type,
|
178
|
+
definition: method_context.method,
|
179
|
+
location: node.loc.name # steep:ignore NoMethod
|
180
|
+
)
|
181
|
+
end
|
169
182
|
end
|
170
183
|
|
171
184
|
when :const, :casgn
|
172
|
-
context = typing.
|
185
|
+
context = typing.cursor_context.context or raise
|
173
186
|
|
174
187
|
type = typing.type_of(node: node)
|
175
188
|
const_name = typing.source_index.reference(constant_node: node)
|
@@ -178,7 +191,7 @@ module Steep
|
|
178
191
|
entry = context.env.constant_entry(const_name) or return
|
179
192
|
|
180
193
|
return ConstantContent.new(
|
181
|
-
location: node.location.name,
|
194
|
+
location: node.location.name, # steep:ignore NoMethod
|
182
195
|
full_name: const_name,
|
183
196
|
type: type,
|
184
197
|
decl: entry
|
@@ -11,7 +11,7 @@ module Steep
|
|
11
11
|
arguments = [] #: Array[String]
|
12
12
|
arguments.push(*method_type.type.required_positionals.map(&:to_s))
|
13
13
|
arguments.push(*method_type.type.optional_positionals.map {|p| "?#{p}"})
|
14
|
-
arguments.push("*#{
|
14
|
+
arguments.push("*#{method_type.type.rest_positionals}") if method_type.type.rest_positionals
|
15
15
|
arguments.push(*method_type.type.trailing_positionals.map(&:to_s))
|
16
16
|
arguments.push(*method_type.type.required_keywords.map {|name, param| "#{name}: #{param}" })
|
17
17
|
arguments.push(*method_type.type.optional_keywords.map {|name, param| "?#{name}: #{param}" })
|
@@ -76,7 +76,8 @@ module Steep
|
|
76
76
|
def type_check!(line:, column:)
|
77
77
|
source = self.source.without_unrelated_defs(line: line, column: column)
|
78
78
|
resolver = RBS::Resolver::ConstantResolver.new(builder: subtyping.factory.definition_builder)
|
79
|
-
|
79
|
+
pos = self.source.buffer.loc_to_pos([line, column])
|
80
|
+
TypeCheckService.type_check(source: source, subtyping: subtyping, constant_resolver: resolver, cursor: pos)
|
80
81
|
end
|
81
82
|
|
82
83
|
def last_argument_nodes_for(argument_nodes:, line:, column:)
|
@@ -99,7 +100,7 @@ module Steep
|
|
99
100
|
|
100
101
|
def signature_help_for(node, argument, last_argument, typing)
|
101
102
|
call = typing.call_of(node: node)
|
102
|
-
context = typing.
|
103
|
+
context = typing.cursor_context.context or raise
|
103
104
|
|
104
105
|
items = [] #: Array[Item]
|
105
106
|
index = nil #: Integer?
|
@@ -113,14 +114,14 @@ module Steep
|
|
113
114
|
shape = shape.public_shape if private_send?(node)
|
114
115
|
|
115
116
|
if method = shape.methods[call.method_name]
|
116
|
-
method.
|
117
|
-
defn =
|
117
|
+
method.overloads.each.with_index do |overload, i|
|
118
|
+
defn = overload.method_defs[0]
|
118
119
|
|
119
120
|
active_parameter = active_parameter_for(defn&.type, argument, last_argument, node)
|
120
|
-
items << Item.new(subtyping.factory.method_type_1(method_type), defn&.comment, active_parameter)
|
121
|
+
items << Item.new(subtyping.factory.method_type_1(overload.method_type), defn&.comment, active_parameter)
|
121
122
|
|
122
123
|
if call.is_a?(MethodCall::Typed)
|
123
|
-
if
|
124
|
+
if call.method_decls.intersect?(overload.method_decls(call.method_name).to_set)
|
124
125
|
index = i
|
125
126
|
end
|
126
127
|
end
|
@@ -136,6 +137,7 @@ module Steep
|
|
136
137
|
|
137
138
|
def active_parameter_for(method_type, argument_nodes, last_argument_nodes, node)
|
138
139
|
return unless method_type
|
140
|
+
return unless method_type.type.is_a?(RBS::Types::Function)
|
139
141
|
|
140
142
|
positionals = method_type.type.required_positionals.size + method_type.type.optional_positionals.size + (method_type.type.rest_positionals ? 1 : 0) + method_type.type.trailing_positionals.size
|
141
143
|
|
@@ -156,6 +156,7 @@ module Steep
|
|
156
156
|
old_text = files[path]&.content
|
157
157
|
content = cs.inject(old_text || "") {|text, change| change.apply_to(text) }
|
158
158
|
|
159
|
+
content ||= "" # It was not clear why `content` can be `nil`, but it happens with `master_test`.
|
159
160
|
buffer = RBS::Buffer.new(name: path, content: content)
|
160
161
|
|
161
162
|
update[path] =
|
@@ -228,7 +229,6 @@ module Steep
|
|
228
229
|
end
|
229
230
|
|
230
231
|
def update_env(updated_files, paths:)
|
231
|
-
|
232
232
|
Steep.logger.tagged "#update_env" do
|
233
233
|
errors = [] #: Array[RBS::BaseError]
|
234
234
|
new_decls = Set[].compare_by_identity #: Set[RBS::AST::Declarations::t]
|
@@ -139,8 +139,11 @@ module Steep
|
|
139
139
|
|
140
140
|
case service.status
|
141
141
|
when SignatureService::SyntaxErrorStatus, SignatureService::AncestorErrorStatus
|
142
|
-
service.status.diagnostics.group_by {|diag|
|
143
|
-
|
142
|
+
service.status.diagnostics.group_by {|diag| diag.location&.buffer&.name&.to_s }.each do |path_string, diagnostics|
|
143
|
+
if path_string
|
144
|
+
path = Pathname(path_string)
|
145
|
+
signature_diagnostics[path].push(*diagnostics)
|
146
|
+
end
|
144
147
|
end
|
145
148
|
when SignatureService::LoadedStatus
|
146
149
|
validation_diagnostics = signature_validation_diagnostics[target.name] || {}
|
@@ -230,6 +233,7 @@ module Steep
|
|
230
233
|
case service.status
|
231
234
|
when SignatureService::SyntaxErrorStatus
|
232
235
|
diagnostics = service.status.diagnostics.select do |diag|
|
236
|
+
diag.location or raise
|
233
237
|
Pathname(diag.location.buffer.name) == path &&
|
234
238
|
(diag.is_a?(Diagnostic::Signature::SyntaxError) || diag.is_a?(Diagnostic::Signature::UnexpectedError))
|
235
239
|
end
|
@@ -239,12 +243,15 @@ module Steep
|
|
239
243
|
end
|
240
244
|
|
241
245
|
when SignatureService::AncestorErrorStatus
|
242
|
-
diagnostics = service.status.diagnostics.select
|
246
|
+
diagnostics = service.status.diagnostics.select do |diag|
|
247
|
+
diag.location or raise
|
248
|
+
Pathname(diag.location.buffer.name) == path
|
249
|
+
end
|
243
250
|
accumulated_diagnostics.push(*diagnostics)
|
244
251
|
yield [path, accumulated_diagnostics]
|
245
252
|
|
246
253
|
when SignatureService::LoadedStatus
|
247
|
-
validator = Signature::Validator.new(checker: service.current_subtyping)
|
254
|
+
validator = Signature::Validator.new(checker: service.current_subtyping || raise)
|
248
255
|
type_names = service.type_names(paths: Set[path], env: service.latest_env).to_set
|
249
256
|
|
250
257
|
unless type_names.empty?
|
@@ -286,7 +293,10 @@ module Steep
|
|
286
293
|
end
|
287
294
|
end
|
288
295
|
|
289
|
-
diagnostics = validator.each_error.select
|
296
|
+
diagnostics = validator.each_error.select do |error|
|
297
|
+
error.location or raise
|
298
|
+
Pathname(error.location.buffer.name) == path
|
299
|
+
end
|
290
300
|
accumulated_diagnostics.push(*diagnostics)
|
291
301
|
yield [path, accumulated_diagnostics]
|
292
302
|
end
|
@@ -353,7 +363,7 @@ module Steep
|
|
353
363
|
def type_check_file(target:, subtyping:, path:, text:)
|
354
364
|
Steep.logger.tagged "#type_check_file(#{path}@#{target.name})" do
|
355
365
|
source = Source.parse(text, path: path, factory: subtyping.factory)
|
356
|
-
typing = TypeCheckService.type_check(source: source, subtyping: subtyping, constant_resolver: yield)
|
366
|
+
typing = TypeCheckService.type_check(source: source, subtyping: subtyping, constant_resolver: yield, cursor: nil)
|
357
367
|
ignores = Source::IgnoreRanges.new(ignores: source.ignores)
|
358
368
|
SourceFile.with_typing(path: path, content: text, node: source.node, typing: typing, ignores: ignores)
|
359
369
|
end
|
@@ -361,7 +371,7 @@ module Steep
|
|
361
371
|
error = Diagnostic::Ruby::SyntaxError.new(message: exn.message, location: exn.location)
|
362
372
|
SourceFile.with_syntax_error(path: path, content: text, error: error)
|
363
373
|
rescue ::Parser::SyntaxError => exn
|
364
|
-
error = Diagnostic::Ruby::SyntaxError.new(message: exn.message, location: exn.diagnostic.location)
|
374
|
+
error = Diagnostic::Ruby::SyntaxError.new(message: exn.message, location: (_ = exn).diagnostic.location)
|
365
375
|
SourceFile.with_syntax_error(path: path, content: text, error: error)
|
366
376
|
rescue EncodingError => exn
|
367
377
|
SourceFile.no_data(path: path, content: "")
|
@@ -370,7 +380,7 @@ module Steep
|
|
370
380
|
SourceFile.no_data(path: path, content: text)
|
371
381
|
end
|
372
382
|
|
373
|
-
def self.type_check(source:, subtyping:, constant_resolver:)
|
383
|
+
def self.type_check(source:, subtyping:, constant_resolver:, cursor:)
|
374
384
|
annotations = source.annotations(block: source.node, factory: subtyping.factory, context: nil)
|
375
385
|
|
376
386
|
definition = subtyping.factory.definition_builder.build_instance(AST::Builtin::Object.module_name)
|
@@ -408,7 +418,7 @@ module Steep
|
|
408
418
|
variable_context: TypeInference::Context::TypeVariableContext.empty
|
409
419
|
)
|
410
420
|
|
411
|
-
typing = Typing.new(source: source, root_context: context)
|
421
|
+
typing = Typing.new(source: source, root_context: context, cursor: cursor)
|
412
422
|
|
413
423
|
construction = TypeConstruction.new(
|
414
424
|
checker: subtyping,
|