steep 1.8.0.dev.2 → 1.8.0.pre.1
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 +33 -0
- 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/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 +4 -4
- 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 +10 -5
- data/lib/steep/server/lsp_formatter.rb +8 -6
- data/lib/steep/server/master.rb +193 -140
- data/lib/steep/server/type_check_worker.rb +18 -19
- data/lib/steep/server/work_done_progress.rb +64 -0
- data/lib/steep/services/completion_provider.rb +24 -22
- data/lib/steep/services/goto_service.rb +3 -2
- data/lib/steep/services/hover_provider/ruby.rb +7 -6
- data/lib/steep/services/signature_help_provider.rb +7 -6
- data/lib/steep/services/signature_service.rb +1 -1
- data/lib/steep/services/type_check_service.rb +3 -3
- data/lib/steep/signature/validator.rb +17 -20
- data/lib/steep/subtyping/check.rb +105 -55
- data/lib/steep/subtyping/constraints.rb +11 -15
- data/lib/steep/type_construction.rb +100 -100
- data/lib/steep/type_inference/block_params.rb +6 -6
- 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 +158 -102
- data/lib/steep/version.rb +1 -1
- data/lib/steep.rb +28 -3
- data/steep.gemspec +2 -2
- metadata +16 -9
- data/lib/steep/type_inference/context_array.rb +0 -112
@@ -1,28 +1,83 @@
|
|
1
1
|
module Steep
|
2
2
|
module Interface
|
3
3
|
class Shape
|
4
|
+
class MethodOverload
|
5
|
+
attr_reader :method_type
|
6
|
+
|
7
|
+
attr_reader :method_defs
|
8
|
+
|
9
|
+
def initialize(method_type, defs)
|
10
|
+
@method_type = method_type
|
11
|
+
@method_defs = defs.sort_by do |defn|
|
12
|
+
buf = +""
|
13
|
+
|
14
|
+
if loc = defn.type.location
|
15
|
+
buf << loc.buffer.name.to_s
|
16
|
+
buf << ":"
|
17
|
+
buf << loc.start_pos.to_s
|
18
|
+
end
|
19
|
+
|
20
|
+
buf
|
21
|
+
end
|
22
|
+
@method_defs.uniq!
|
23
|
+
end
|
24
|
+
|
25
|
+
def subst(s)
|
26
|
+
overload = MethodOverload.new(method_type.subst(s), [])
|
27
|
+
overload.method_defs.replace(method_defs)
|
28
|
+
overload
|
29
|
+
end
|
30
|
+
|
31
|
+
def method_decls(name)
|
32
|
+
method_defs.map do |defn|
|
33
|
+
type_name = defn.implemented_in || defn.defined_in
|
34
|
+
|
35
|
+
if name == :new && defn.member.is_a?(RBS::AST::Members::MethodDefinition) && defn.member.name == :initialize
|
36
|
+
method_name = SingletonMethodName.new(type_name: type_name, method_name: name)
|
37
|
+
else
|
38
|
+
method_name =
|
39
|
+
if defn.member.kind == :singleton
|
40
|
+
SingletonMethodName.new(type_name: defn.defined_in, method_name: name)
|
41
|
+
else
|
42
|
+
# Call the `self?` method an instance method, because the definition is done with instance method definition, not with singleton method
|
43
|
+
InstanceMethodName.new(type_name: defn.defined_in, method_name: name)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
TypeInference::MethodCall::MethodDecl.new(method_def: defn, method_name: method_name)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
4
52
|
class Entry
|
5
|
-
|
6
|
-
|
53
|
+
attr_reader :method_name
|
54
|
+
|
55
|
+
def initialize(overloads: nil, private_method:, method_name:, &block)
|
56
|
+
@overloads = overloads
|
7
57
|
@generator = block
|
8
58
|
@private_method = private_method
|
59
|
+
@method_name = method_name
|
9
60
|
end
|
10
61
|
|
11
62
|
def force
|
12
|
-
unless @
|
13
|
-
@
|
63
|
+
unless @overloads
|
64
|
+
@overloads = @generator&.call
|
14
65
|
@generator = nil
|
15
66
|
end
|
16
67
|
end
|
17
68
|
|
18
|
-
def
|
69
|
+
def overloads
|
19
70
|
force
|
20
|
-
@
|
71
|
+
@overloads or raise
|
72
|
+
end
|
73
|
+
|
74
|
+
def method_types
|
75
|
+
overloads.map(&:method_type)
|
21
76
|
end
|
22
77
|
|
23
78
|
def has_method_type?
|
24
79
|
force
|
25
|
-
@
|
80
|
+
@overloads ? true : false
|
26
81
|
end
|
27
82
|
|
28
83
|
def to_s
|
@@ -50,7 +105,7 @@ module Steep
|
|
50
105
|
def initialize(substs:, methods:)
|
51
106
|
@substs = substs
|
52
107
|
@methods = methods
|
53
|
-
@resolved_methods =
|
108
|
+
@resolved_methods = {}
|
54
109
|
end
|
55
110
|
|
56
111
|
def key?(name)
|
@@ -72,8 +127,9 @@ module Steep
|
|
72
127
|
resolved_methods[name] ||= begin
|
73
128
|
entry = methods[name]
|
74
129
|
Entry.new(
|
75
|
-
|
76
|
-
|
130
|
+
method_name: name,
|
131
|
+
overloads: entry.overloads.map do |overload|
|
132
|
+
overload.subst(subst)
|
77
133
|
end,
|
78
134
|
private_method: entry.private_method?
|
79
135
|
)
|
@@ -6,13 +6,15 @@ module Steep
|
|
6
6
|
attr_reader :variance
|
7
7
|
attr_reader :unchecked
|
8
8
|
attr_reader :location
|
9
|
+
attr_reader :default_type
|
9
10
|
|
10
|
-
def initialize(name:, upper_bound:, variance:, unchecked:, location: nil)
|
11
|
+
def initialize(name:, upper_bound:, variance:, unchecked:, location: nil, default_type:)
|
11
12
|
@name = name
|
12
13
|
@upper_bound = upper_bound
|
13
14
|
@variance = variance
|
14
15
|
@unchecked = unchecked
|
15
16
|
@location = location
|
17
|
+
@default_type = default_type
|
16
18
|
end
|
17
19
|
|
18
20
|
def ==(other)
|
@@ -20,13 +22,14 @@ module Steep
|
|
20
22
|
other.name == name &&
|
21
23
|
other.upper_bound == upper_bound &&
|
22
24
|
other.variance == variance &&
|
23
|
-
other.unchecked == unchecked
|
25
|
+
other.unchecked == unchecked &&
|
26
|
+
other.default_type == default_type
|
24
27
|
end
|
25
28
|
|
26
29
|
alias eql? ==
|
27
30
|
|
28
31
|
def hash
|
29
|
-
name.hash ^ upper_bound.hash ^ variance.hash ^ unchecked.hash
|
32
|
+
name.hash ^ upper_bound.hash ^ variance.hash ^ unchecked.hash ^ default_type.hash
|
30
33
|
end
|
31
34
|
|
32
35
|
def self.rename(params, conflicting_names = params.map(&:name), new_names = conflicting_names.map {|n| AST::Types::Var.fresh_name(n) })
|
@@ -44,7 +47,8 @@ module Steep
|
|
44
47
|
upper_bound: param.upper_bound&.subst(subst),
|
45
48
|
variance: param.variance,
|
46
49
|
unchecked: param.unchecked,
|
47
|
-
location: param.location
|
50
|
+
location: param.location,
|
51
|
+
default_type: param.default_type&.subst(subst)
|
48
52
|
)
|
49
53
|
else
|
50
54
|
param
|
@@ -80,19 +84,28 @@ module Steep
|
|
80
84
|
buf
|
81
85
|
end
|
82
86
|
|
83
|
-
def update(name: self.name, upper_bound: self.upper_bound, variance: self.variance, unchecked: self.unchecked, location: self.location)
|
87
|
+
def update(name: self.name, upper_bound: self.upper_bound, variance: self.variance, unchecked: self.unchecked, location: self.location, default_type: self.default_type)
|
84
88
|
TypeParam.new(
|
85
89
|
name: name,
|
86
90
|
upper_bound: upper_bound,
|
87
91
|
variance: variance,
|
88
92
|
unchecked: unchecked,
|
89
|
-
location: location
|
93
|
+
location: location,
|
94
|
+
default_type: default_type
|
90
95
|
)
|
91
96
|
end
|
92
97
|
|
93
98
|
def subst(s)
|
94
99
|
if u = upper_bound
|
95
|
-
|
100
|
+
ub = u.subst(s)
|
101
|
+
end
|
102
|
+
|
103
|
+
if d = default_type
|
104
|
+
dt = d.subst(s)
|
105
|
+
end
|
106
|
+
|
107
|
+
if ub || dt
|
108
|
+
update(upper_bound: ub, default_type: dt)
|
96
109
|
else
|
97
110
|
self
|
98
111
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Steep
|
2
|
+
class LocatedValue
|
3
|
+
attr_reader :value, :location
|
4
|
+
|
5
|
+
def initialize(value:, location:)
|
6
|
+
@value = value
|
7
|
+
@location = location
|
8
|
+
end
|
9
|
+
|
10
|
+
def ==(other)
|
11
|
+
other.is_a?(LocatedValue) && other.value == value
|
12
|
+
end
|
13
|
+
|
14
|
+
alias eql? ==
|
15
|
+
|
16
|
+
def hash
|
17
|
+
value.hash # steep:ignore NoMethod
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -24,16 +24,14 @@ module Steep
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
def load_files(
|
27
|
+
def load_files(input)
|
28
28
|
Steep.logger.tagged "#load_files" do
|
29
29
|
push_buffer do |changes|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
project.targets.each do |target|
|
34
|
-
loader.load_changes(target.source_pattern, commandline_args, changes: changes)
|
35
|
-
loader.load_changes(target.signature_pattern, changes: changes)
|
30
|
+
input.each do |filename, content|
|
31
|
+
if content.is_a?(Hash)
|
32
|
+
content = Base64.decode64(content[:text]).force_encoding(Encoding::UTF_8)
|
36
33
|
end
|
34
|
+
changes[Pathname(filename.to_s)] = [Services::ContentChange.new(text: content)]
|
37
35
|
end
|
38
36
|
end
|
39
37
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Steep
|
2
|
+
module Server
|
3
|
+
module CustomMethods
|
4
|
+
module FileLoad
|
5
|
+
METHOD = "$/steep/file/load"
|
6
|
+
|
7
|
+
def self.notification(params)
|
8
|
+
{ method: METHOD, params: params }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module FileReset
|
13
|
+
METHOD = "$/steep/file/reset"
|
14
|
+
|
15
|
+
def self.notification(params)
|
16
|
+
{ method: METHOD, params: params }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module TypeCheck
|
21
|
+
METHOD = "$/steep/typecheck"
|
22
|
+
|
23
|
+
def self.request(id, params)
|
24
|
+
{ method: METHOD, id: id, params: params }
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.response(id, result)
|
28
|
+
{ id: id, result: result }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
module TypeCheck__Start
|
33
|
+
METHOD = "$/steep/typecheck/start"
|
34
|
+
|
35
|
+
def self.notification(params)
|
36
|
+
{ method: METHOD, params: params }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
module TypeCheck__Progress
|
41
|
+
METHOD = "$/steep/typecheck/progress"
|
42
|
+
|
43
|
+
def self.notification(params)
|
44
|
+
{ method: METHOD, params: params }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
module Stats
|
49
|
+
METHOD = "$/steep/stats"
|
50
|
+
|
51
|
+
def self.request(id)
|
52
|
+
{ method: METHOD, id: id, params: nil }
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.response(id, result)
|
56
|
+
{ id: id, result: result }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -25,12 +25,19 @@ module Steep
|
|
25
25
|
end
|
26
26
|
|
27
27
|
if proc.equal?(last_task)
|
28
|
-
|
28
|
+
unless @cancelled
|
29
|
+
proc[]
|
30
|
+
end
|
29
31
|
end
|
30
32
|
end
|
31
33
|
end
|
32
34
|
end
|
33
35
|
|
36
|
+
def cancel
|
37
|
+
@cancelled = true
|
38
|
+
queue.clear()
|
39
|
+
end
|
40
|
+
|
34
41
|
def execute(&block)
|
35
42
|
@last_task = block
|
36
43
|
scheduled_at = Time.now + delay
|
@@ -82,17 +82,22 @@ module Steep
|
|
82
82
|
def handle_request(request)
|
83
83
|
case request[:method]
|
84
84
|
when "initialize"
|
85
|
-
load_files(project: project, commandline_args: [])
|
86
|
-
queue_job ApplyChangeJob.new
|
87
85
|
writer.write({ id: request[:id], result: nil })
|
88
86
|
|
89
87
|
when "textDocument/didChange"
|
90
88
|
collect_changes(request)
|
91
89
|
queue_job ApplyChangeJob.new
|
92
90
|
|
93
|
-
when
|
94
|
-
|
95
|
-
|
91
|
+
when CustomMethods::FileLoad::METHOD
|
92
|
+
params = request[:params] #: CustomMethods::FileLoad::params
|
93
|
+
input = params[:content]
|
94
|
+
load_files(input)
|
95
|
+
queue_job ApplyChangeJob.new
|
96
|
+
|
97
|
+
when CustomMethods::FileReset::METHOD
|
98
|
+
params = request[:params] #: CustomMethods::FileReset::params
|
99
|
+
uri = params[:uri]
|
100
|
+
text = params[:content]
|
96
101
|
reset_change(uri: uri, text: text)
|
97
102
|
queue_job ApplyChangeJob.new
|
98
103
|
|
@@ -36,7 +36,8 @@ module Steep
|
|
36
36
|
----
|
37
37
|
MD
|
38
38
|
|
39
|
-
|
39
|
+
method_decls = call.method_decls.sort_by {|decl| decl.method_name.to_s }
|
40
|
+
method_types = method_decls.map(&:method_type)
|
40
41
|
|
41
42
|
if call.is_a?(TypeInference::MethodCall::Special)
|
42
43
|
method_types = [
|
@@ -52,7 +53,8 @@ module Steep
|
|
52
53
|
MD
|
53
54
|
end
|
54
55
|
when TypeInference::MethodCall::Error
|
55
|
-
|
56
|
+
method_decls = call.method_decls.sort_by {|decl| decl.method_name.to_s }
|
57
|
+
method_types = method_decls.map {|decl| decl.method_type }
|
56
58
|
|
57
59
|
header = <<~MD
|
58
60
|
**🚨 No compatible method type found**
|
@@ -61,8 +63,8 @@ module Steep
|
|
61
63
|
MD
|
62
64
|
end
|
63
65
|
|
64
|
-
method_names =
|
65
|
-
docs =
|
66
|
+
method_names = method_decls.map {|decl| decl.method_name.relative }
|
67
|
+
docs = method_decls.map {|decl| [decl.method_name, decl.method_def.comment] }.to_h
|
66
68
|
|
67
69
|
if header
|
68
70
|
io.puts header
|
@@ -373,8 +375,8 @@ module Steep
|
|
373
375
|
end
|
374
376
|
s << param.name.to_s
|
375
377
|
|
376
|
-
if param.
|
377
|
-
s << " < #{param.
|
378
|
+
if param.upper_bound_type
|
379
|
+
s << " < #{param.upper_bound_type.to_s}"
|
378
380
|
end
|
379
381
|
|
380
382
|
s
|