steep 2.0.0 → 2.1.0
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 +35 -0
- data/CLAUDE.md +2 -2
- data/README.md +3 -3
- data/Rakefile +350 -147
- data/bin/steep-check.rb +4 -4
- data/doc/release.md +264 -0
- data/lib/steep/ast/types/helper.rb +0 -1
- data/lib/steep/ast/types/name.rb +1 -1
- data/lib/steep/cli.rb +32 -3
- data/lib/steep/daemon.rb +49 -9
- data/lib/steep/diagnostic/ruby.rb +4 -4
- data/lib/steep/drivers/init.rb +4 -3
- data/lib/steep/drivers/langserver.rb +33 -1
- data/lib/steep/drivers/query.rb +40 -2
- data/lib/steep/interface/builder.rb +24 -4
- data/lib/steep/node_helper.rb +2 -2
- data/lib/steep/server/base_worker.rb +15 -0
- data/lib/steep/server/command_socket.rb +181 -0
- data/lib/steep/server/custom_methods.rb +12 -0
- data/lib/steep/server/master.rb +383 -2
- data/lib/steep/server/type_check_worker.rb +48 -2
- data/lib/steep/services/goto_service.rb +7 -3
- data/lib/steep/services/hover_provider/content.rb +1 -1
- data/lib/steep/services/hover_provider/ruby.rb +1 -1
- data/lib/steep/services/signature_help_provider.rb +1 -1
- data/lib/steep/source.rb +9 -10
- data/lib/steep/subtyping/check.rb +6 -3
- data/lib/steep/tagged_logging.rb +4 -1
- data/lib/steep/type_construction.rb +37 -16
- data/lib/steep/type_inference/case_when.rb +2 -2
- data/lib/steep/type_inference/logic_type_interpreter.rb +6 -3
- data/lib/steep/type_inference/send_args.rb +9 -5
- data/lib/steep/typing.rb +3 -3
- data/lib/steep/version.rb +1 -1
- data/lib/steep.rb +1 -0
- data/steep.gemspec +2 -8
- metadata +7 -5
|
@@ -189,7 +189,7 @@ module Steep
|
|
|
189
189
|
|
|
190
190
|
relation.type!
|
|
191
191
|
|
|
192
|
-
Steep.logger.tagged "#{relation.sub_type} <: #{relation.super_type}" do
|
|
192
|
+
Steep.logger.tagged(-> { "#{relation.sub_type} <: #{relation.super_type}" }) do
|
|
193
193
|
bounds = cache_bounds(relation)
|
|
194
194
|
fvs = relation.sub_type.free_variables + relation.super_type.free_variables
|
|
195
195
|
cached = cache[relation, @self_type, @instance_type, @class_type, bounds]
|
|
@@ -201,7 +201,7 @@ module Steep
|
|
|
201
201
|
else
|
|
202
202
|
push_assumption(relation) do
|
|
203
203
|
check_type0(relation).tap do |result|
|
|
204
|
-
Steep.logger.debug "result=#{result.class}"
|
|
204
|
+
Steep.logger.debug { "result=#{result.class}" }
|
|
205
205
|
cache[relation, @self_type, @instance_type, @class_type, bounds] = result
|
|
206
206
|
end
|
|
207
207
|
end
|
|
@@ -644,6 +644,9 @@ module Steep
|
|
|
644
644
|
|
|
645
645
|
All(relation) do |result|
|
|
646
646
|
sub_args.zip(sup_args, sup_params.each).each do |sub_arg, sup_arg, sup_param|
|
|
647
|
+
sup_arg or raise
|
|
648
|
+
sup_param or raise
|
|
649
|
+
|
|
647
650
|
case sup_param.variance
|
|
648
651
|
when :covariant
|
|
649
652
|
result.add(Relation.new(sub_type: sub_arg, super_type: sup_arg)) do |rel|
|
|
@@ -854,7 +857,7 @@ module Steep
|
|
|
854
857
|
end
|
|
855
858
|
|
|
856
859
|
def check_method_type(name, relation)
|
|
857
|
-
Steep.logger.tagged "#{name} : #{relation.sub_type} <: #{relation.super_type}" do
|
|
860
|
+
Steep.logger.tagged(-> { "#{name} : #{relation.sub_type} <: #{relation.super_type}" }) do
|
|
858
861
|
relation.method!
|
|
859
862
|
|
|
860
863
|
sub_type, super_type = relation
|
data/lib/steep/tagged_logging.rb
CHANGED
|
@@ -653,7 +653,6 @@ module Steep
|
|
|
653
653
|
instance_definition: instance_definition
|
|
654
654
|
)
|
|
655
655
|
|
|
656
|
-
singleton_definition = checker.factory.definition_builder.build_singleton(module_context.class_name)
|
|
657
656
|
type_env =
|
|
658
657
|
TypeInference::TypeEnvBuilder.new(
|
|
659
658
|
TypeInference::TypeEnvBuilder::Command::ImportGlobalDeclarations.new(checker.factory),
|
|
@@ -730,7 +729,7 @@ module Steep
|
|
|
730
729
|
end
|
|
731
730
|
|
|
732
731
|
def synthesize(node, hint: nil, condition: false)
|
|
733
|
-
Steep.logger.tagged "synthesize:(#{node.location&.yield_self {|loc| loc.expression.to_s.split(/:/, 2).last } || "-"})" do
|
|
732
|
+
Steep.logger.tagged(-> { "synthesize:(#{node.location&.yield_self {|loc| loc.expression.to_s.split(/:/, 2).last } || "-"})" }) do
|
|
734
733
|
Steep.logger.debug node.type
|
|
735
734
|
case node.type
|
|
736
735
|
when :begin, :kwbegin
|
|
@@ -781,7 +780,7 @@ module Steep
|
|
|
781
780
|
end
|
|
782
781
|
|
|
783
782
|
if rhs
|
|
784
|
-
rhs_type, rhs_constr,
|
|
783
|
+
rhs_type, rhs_constr, _ = synthesize(rhs, hint: hint).to_ary
|
|
785
784
|
|
|
786
785
|
constr = rhs_constr.update_type_env do |type_env|
|
|
787
786
|
var_type = rhs_type
|
|
@@ -1761,6 +1760,11 @@ module Steep
|
|
|
1761
1760
|
else
|
|
1762
1761
|
if hint
|
|
1763
1762
|
tuples = select_flatten_types(hint) {|type| type.is_a?(AST::Types::Tuple) } #: Array[AST::Types::Tuple]
|
|
1763
|
+
if tuples.empty?
|
|
1764
|
+
if converted = try_convert(hint, :to_ary)
|
|
1765
|
+
tuples = select_flatten_types(converted) {|type| type.is_a?(AST::Types::Tuple) } #: Array[AST::Types::Tuple]
|
|
1766
|
+
end
|
|
1767
|
+
end
|
|
1764
1768
|
unless tuples.empty?
|
|
1765
1769
|
fallback_pair = nil #: Pair?
|
|
1766
1770
|
tuples.each do |tuple|
|
|
@@ -1913,7 +1917,7 @@ module Steep
|
|
|
1913
1917
|
yield_self do
|
|
1914
1918
|
cond, true_clause, false_clause = node.children
|
|
1915
1919
|
|
|
1916
|
-
|
|
1920
|
+
_, constr = synthesize(cond, condition: true).to_ary
|
|
1917
1921
|
interpreter = TypeInference::LogicTypeInterpreter.new(subtyping: checker, typing: constr.typing, config: builder_config)
|
|
1918
1922
|
truthy, falsy = interpreter.eval(env: constr.context.type_env, node: cond)
|
|
1919
1923
|
|
|
@@ -2045,7 +2049,7 @@ module Steep
|
|
|
2045
2049
|
branch_reachable = false
|
|
2046
2050
|
|
|
2047
2051
|
tests.each do |test|
|
|
2048
|
-
|
|
2052
|
+
_, condition_constr = condition_constr.synthesize(test, condition: true)
|
|
2049
2053
|
truthy, falsy = interpreter.eval(env: condition_constr.context.type_env, node: test)
|
|
2050
2054
|
truthy_env = truthy.env
|
|
2051
2055
|
falsy_env = falsy.env
|
|
@@ -2295,7 +2299,7 @@ module Steep
|
|
|
2295
2299
|
when :while, :until
|
|
2296
2300
|
yield_self do
|
|
2297
2301
|
cond, body = node.children
|
|
2298
|
-
|
|
2302
|
+
_, constr = synthesize(cond, condition: true).to_ary
|
|
2299
2303
|
|
|
2300
2304
|
interpreter = TypeInference::LogicTypeInterpreter.new(subtyping: checker, typing: typing, config: builder_config)
|
|
2301
2305
|
truthy, falsy = interpreter.eval(env: constr.context.type_env, node: cond)
|
|
@@ -2347,7 +2351,7 @@ module Steep
|
|
|
2347
2351
|
.for_branch(body, break_context: TypeInference::Context::BreakContext.new(break_type: hint || AST::Builtin.nil_type, next_type: nil))
|
|
2348
2352
|
|
|
2349
2353
|
typing.cursor_context.set_node_context(body, for_loop.context)
|
|
2350
|
-
_,
|
|
2354
|
+
_, _, body_context = for_loop.synthesize(body)
|
|
2351
2355
|
|
|
2352
2356
|
constr = cond_constr.update_type_env {|env| env.join(env, body_context.type_env) }
|
|
2353
2357
|
|
|
@@ -2696,7 +2700,7 @@ module Steep
|
|
|
2696
2700
|
constr.add_typing(node, type: type)
|
|
2697
2701
|
end
|
|
2698
2702
|
|
|
2699
|
-
when :block, :numblock, :send, :csend
|
|
2703
|
+
when :block, :numblock, :itblock, :send, :csend
|
|
2700
2704
|
synthesize_sendish(node, hint: hint, tapp: nil)
|
|
2701
2705
|
|
|
2702
2706
|
when :forwarded_args, :forward_arg
|
|
@@ -2772,6 +2776,20 @@ module Steep
|
|
|
2772
2776
|
|
|
2773
2777
|
params = Parser::AST::Node.new(:args, arg_nodes)
|
|
2774
2778
|
|
|
2779
|
+
if send_node.type == :lambda
|
|
2780
|
+
# @type var node: Parser::AST::Node & Parser::AST::_BlockNode
|
|
2781
|
+
type_lambda(node, params_node: params, body_node: body, type_hint: hint)
|
|
2782
|
+
else
|
|
2783
|
+
type_send(node, send_node: send_node, block_params: params, block_body: body, unwrap: send_node.type == :csend, tapp: tapp, hint: hint)
|
|
2784
|
+
end
|
|
2785
|
+
end
|
|
2786
|
+
when :itblock
|
|
2787
|
+
yield_self do
|
|
2788
|
+
send_node, _name, body = node.children
|
|
2789
|
+
|
|
2790
|
+
arg_nodes = [Parser::AST::Node.new(:procarg0, [:it])]
|
|
2791
|
+
params = Parser::AST::Node.new(:args, arg_nodes)
|
|
2792
|
+
|
|
2775
2793
|
if send_node.type == :lambda
|
|
2776
2794
|
# @type var node: Parser::AST::Node & Parser::AST::_BlockNode
|
|
2777
2795
|
type_lambda(node, params_node: params, body_node: body, type_hint: hint)
|
|
@@ -2872,10 +2890,8 @@ module Steep
|
|
|
2872
2890
|
if node.type == :splat
|
|
2873
2891
|
asgn_node = node.children[0]
|
|
2874
2892
|
next unless asgn_node
|
|
2875
|
-
var_type = asgn_node.type
|
|
2876
2893
|
else
|
|
2877
2894
|
asgn_node = node
|
|
2878
|
-
var_type = type
|
|
2879
2895
|
end
|
|
2880
2896
|
|
|
2881
2897
|
case asgn_node.type
|
|
@@ -3150,11 +3166,14 @@ module Steep
|
|
|
3150
3166
|
block =
|
|
3151
3167
|
if block_param = params.block_param
|
|
3152
3168
|
if block_param_type = block_param.type
|
|
3153
|
-
|
|
3169
|
+
# Expanding aliases because the cases below test the structure of the type
|
|
3170
|
+
expanded_type = deep_expand_alias(block_param_type) || block_param_type
|
|
3171
|
+
|
|
3172
|
+
case expanded_type
|
|
3154
3173
|
when AST::Types::Proc
|
|
3155
|
-
Interface::Block.new(type:
|
|
3174
|
+
Interface::Block.new(type: expanded_type.type, optional: false, self_type: expanded_type.self_type)
|
|
3156
3175
|
else
|
|
3157
|
-
if proc_type = optional_proc?(
|
|
3176
|
+
if proc_type = optional_proc?(expanded_type)
|
|
3158
3177
|
Interface::Block.new(type: proc_type.type, optional: true, self_type: proc_type.self_type)
|
|
3159
3178
|
else
|
|
3160
3179
|
block_constr.typing.add_error(
|
|
@@ -3346,7 +3365,7 @@ module Steep
|
|
|
3346
3365
|
end
|
|
3347
3366
|
end
|
|
3348
3367
|
|
|
3349
|
-
if node.type == :csend || ((node.type == :block || node.type == :numblock) && node.children[0].type == :csend)
|
|
3368
|
+
if node.type == :csend || ((node.type == :block || node.type == :numblock || node.type == :itblock) && node.children[0].type == :csend)
|
|
3350
3369
|
optional_type = AST::Types::Union.build(types: [call.return_type, AST::Builtin.nil_type])
|
|
3351
3370
|
call = call.with_return_type(optional_type)
|
|
3352
3371
|
end
|
|
@@ -3509,7 +3528,7 @@ module Steep
|
|
|
3509
3528
|
|
|
3510
3529
|
when AST::Types::Any
|
|
3511
3530
|
case node.type
|
|
3512
|
-
when :block, :numblock
|
|
3531
|
+
when :block, :numblock, :itblock
|
|
3513
3532
|
# @type var node: Parser::AST::Node & Parser::AST::_BlockNode
|
|
3514
3533
|
block_annotations = source.annotations(block: node, factory: checker.factory, context: nesting)
|
|
3515
3534
|
block_params or raise
|
|
@@ -4344,7 +4363,9 @@ module Steep
|
|
|
4344
4363
|
when arg.compatible?
|
|
4345
4364
|
if arg.node
|
|
4346
4365
|
# Block pass (&block) is given
|
|
4347
|
-
node_type
|
|
4366
|
+
# Passing `proc_type` instead of `node_type` because a block-pass argument is a proc, not `nil`.
|
|
4367
|
+
# `nil` is still allowed by the `node_type` check below.
|
|
4368
|
+
node_type, constr = constr.synthesize(arg.node, hint: arg.proc_type)
|
|
4348
4369
|
|
|
4349
4370
|
nil_given =
|
|
4350
4371
|
constr.check_relation(sub_type: node_type, super_type: AST::Builtin.nil_type).success? &&
|
|
@@ -20,14 +20,14 @@ module Steep
|
|
|
20
20
|
|
|
21
21
|
latest_constr, unreachable_pattern = latest_result
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
yield(test_node, latest_constr, unreachable_pattern)
|
|
24
24
|
truthy_result, falsy_result = logic.eval(env: latest_constr.context.type_env, node: test_node)
|
|
25
25
|
|
|
26
26
|
pattern_results << [pat, truthy_result, falsy_result]
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
def latest_result
|
|
30
|
-
if (_,
|
|
30
|
+
if (_, _, falsy = pattern_results.last)
|
|
31
31
|
[
|
|
32
32
|
initial_constr.update_type_env { falsy.env },
|
|
33
33
|
falsy.unreachable
|
|
@@ -564,9 +564,12 @@ module Steep
|
|
|
564
564
|
false_types << type
|
|
565
565
|
end
|
|
566
566
|
else
|
|
567
|
-
# For
|
|
568
|
-
#
|
|
569
|
-
|
|
567
|
+
# For `==`, narrow only when the literal can be a value of `type`.
|
|
568
|
+
# e.g. `Symbol == :fatal` can be true, but `SomeClass == :fatal` cannot.
|
|
569
|
+
literal_type = AST::Types::Literal.new(value: value_node.children[0])
|
|
570
|
+
if !for_receiver || subtyping?(sub_type: literal_type, super_type: type)
|
|
571
|
+
true_types << literal_type
|
|
572
|
+
end
|
|
570
573
|
false_types << type
|
|
571
574
|
end
|
|
572
575
|
end
|
|
@@ -473,16 +473,20 @@ module Steep
|
|
|
473
473
|
end
|
|
474
474
|
end
|
|
475
475
|
|
|
476
|
-
def
|
|
476
|
+
def proc_type
|
|
477
477
|
raise unless block
|
|
478
478
|
|
|
479
|
-
|
|
479
|
+
AST::Types::Proc.new(type: block.type, block: nil, self_type: block.self_type)
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
def node_type
|
|
483
|
+
raise unless block
|
|
480
484
|
|
|
481
485
|
if block.optional?
|
|
482
|
-
|
|
486
|
+
AST::Types::Union.build(types: [proc_type, AST::Builtin.nil_type])
|
|
487
|
+
else
|
|
488
|
+
proc_type
|
|
483
489
|
end
|
|
484
|
-
|
|
485
|
-
type
|
|
486
490
|
end
|
|
487
491
|
end
|
|
488
492
|
|
data/lib/steep/typing.rb
CHANGED
|
@@ -106,7 +106,7 @@ module Steep
|
|
|
106
106
|
set(body_begin_pos..body_end_pos, context)
|
|
107
107
|
end
|
|
108
108
|
|
|
109
|
-
when :block, :numblock
|
|
109
|
+
when :block, :numblock, :itblock
|
|
110
110
|
range = block_range(node)
|
|
111
111
|
set(range, context)
|
|
112
112
|
|
|
@@ -132,7 +132,7 @@ module Steep
|
|
|
132
132
|
node.loc.begin.end_pos # steep:ignore NoMethod
|
|
133
133
|
end
|
|
134
134
|
end_pos = node.loc.end.begin_pos # steep:ignore NoMethod
|
|
135
|
-
when :numblock
|
|
135
|
+
when :numblock, :itblock
|
|
136
136
|
send_node, _ = node.children
|
|
137
137
|
begin_pos = node.loc.begin.end_pos # steep:ignore NoMethod
|
|
138
138
|
end_pos = node.loc.end.begin_pos # steep:ignore NoMethod
|
|
@@ -245,7 +245,7 @@ module Steep
|
|
|
245
245
|
node.loc.begin.end_pos # steep:ignore NoMethod
|
|
246
246
|
end
|
|
247
247
|
end_pos = node.loc.end.begin_pos # steep:ignore NoMethod
|
|
248
|
-
when :numblock
|
|
248
|
+
when :numblock, :itblock
|
|
249
249
|
send_node, _ = node.children
|
|
250
250
|
begin_pos = node.loc.begin.end_pos # steep:ignore NoMethod
|
|
251
251
|
end_pos = node.loc.end.begin_pos # steep:ignore NoMethod
|
data/lib/steep/version.rb
CHANGED
data/lib/steep.rb
CHANGED
|
@@ -133,6 +133,7 @@ require "steep/server/target_group_files"
|
|
|
133
133
|
require "steep/server/type_check_controller"
|
|
134
134
|
require "steep/server/inline_source_change_detector"
|
|
135
135
|
require "steep/server/master"
|
|
136
|
+
require "steep/server/command_socket"
|
|
136
137
|
require "steep/daemon"
|
|
137
138
|
|
|
138
139
|
require "steep/project"
|
data/steep.gemspec
CHANGED
|
@@ -29,20 +29,14 @@ Gem::Specification.new do |spec|
|
|
|
29
29
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
30
30
|
spec.require_paths = ["lib"]
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
# This is to let dependabot use 3.3, instead of 3.1.x.
|
|
34
|
-
# They use `required_ruby_version=` method to detect the Ruby version they use.
|
|
35
|
-
spec.required_ruby_version = ">= 3.3.0"
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
spec.required_ruby_version = '>= 3.2.0'
|
|
32
|
+
spec.required_ruby_version = '>= 3.3.0'
|
|
39
33
|
|
|
40
34
|
spec.add_runtime_dependency "parser", ">= 3.2"
|
|
41
35
|
spec.add_runtime_dependency "prism", ">= 0.25.0"
|
|
42
36
|
spec.add_runtime_dependency "rainbow", ">= 2.2.2", "< 4.0"
|
|
43
37
|
spec.add_runtime_dependency "listen", "~> 3.0"
|
|
44
38
|
spec.add_runtime_dependency "language_server-protocol", ">= 3.17.0.4", "< 4.0"
|
|
45
|
-
spec.add_runtime_dependency "rbs", "~> 4.
|
|
39
|
+
spec.add_runtime_dependency "rbs", "~> 4.2"
|
|
46
40
|
spec.add_runtime_dependency "concurrent-ruby", ">= 1.1.10"
|
|
47
41
|
spec.add_runtime_dependency "terminal-table", ">= 2", "< 5"
|
|
48
42
|
spec.add_runtime_dependency "securerandom", ">= 0.1"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: steep
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Soutaro Matsumoto
|
|
@@ -97,14 +97,14 @@ dependencies:
|
|
|
97
97
|
requirements:
|
|
98
98
|
- - "~>"
|
|
99
99
|
- !ruby/object:Gem::Version
|
|
100
|
-
version: '4.
|
|
100
|
+
version: '4.2'
|
|
101
101
|
type: :runtime
|
|
102
102
|
prerelease: false
|
|
103
103
|
version_requirements: !ruby/object:Gem::Requirement
|
|
104
104
|
requirements:
|
|
105
105
|
- - "~>"
|
|
106
106
|
- !ruby/object:Gem::Version
|
|
107
|
-
version: '4.
|
|
107
|
+
version: '4.2'
|
|
108
108
|
- !ruby/object:Gem::Dependency
|
|
109
109
|
name: concurrent-ruby
|
|
110
110
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -267,6 +267,7 @@ files:
|
|
|
267
267
|
- bin/steep-check.rb
|
|
268
268
|
- bin/steep-prof
|
|
269
269
|
- doc/narrowing.md
|
|
270
|
+
- doc/release.md
|
|
270
271
|
- doc/shape.md
|
|
271
272
|
- exe/steep
|
|
272
273
|
- guides/README.md
|
|
@@ -361,6 +362,7 @@ files:
|
|
|
361
362
|
- lib/steep/range_extension.rb
|
|
362
363
|
- lib/steep/server/base_worker.rb
|
|
363
364
|
- lib/steep/server/change_buffer.rb
|
|
365
|
+
- lib/steep/server/command_socket.rb
|
|
364
366
|
- lib/steep/server/custom_methods.rb
|
|
365
367
|
- lib/steep/server/delay_queue.rb
|
|
366
368
|
- lib/steep/server/inline_source_change_detector.rb
|
|
@@ -441,14 +443,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
441
443
|
requirements:
|
|
442
444
|
- - ">="
|
|
443
445
|
- !ruby/object:Gem::Version
|
|
444
|
-
version: 3.
|
|
446
|
+
version: 3.3.0
|
|
445
447
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
446
448
|
requirements:
|
|
447
449
|
- - ">="
|
|
448
450
|
- !ruby/object:Gem::Version
|
|
449
451
|
version: '0'
|
|
450
452
|
requirements: []
|
|
451
|
-
rubygems_version: 4.0.
|
|
453
|
+
rubygems_version: 4.0.19
|
|
452
454
|
specification_version: 4
|
|
453
455
|
summary: Gradual Typing for Ruby
|
|
454
456
|
test_files: []
|