steep 1.5.0.pre.2 → 1.5.0.pre.4
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 +30 -0
- data/Gemfile.lock +1 -1
- data/lib/steep/ast/node/type_application.rb +4 -1
- data/lib/steep/ast/node/type_assertion.rb +4 -2
- data/lib/steep/ast/types/factory.rb +9 -4
- data/lib/steep/diagnostic/ruby.rb +3 -3
- data/lib/steep/server/interaction_worker.rb +4 -2
- data/lib/steep/type_construction.rb +52 -58
- data/lib/steep/type_inference/logic_type_interpreter.rb +4 -0
- data/lib/steep/version.rb +1 -1
- data/sig/steep/server/interaction_worker.rbs +4 -0
- data/sig/steep/type_construction.rbs +14 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cfb1de89ec50042cf06306ab17717671e8b6a8451ea2885b4af8085226f7994e
|
4
|
+
data.tar.gz: 1b67eb25821061afe42c8c4dd644b30370e866ac9ef8066cb77031799c981145
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1f0b3400822be747c45ed1d5c2cdfbddf8c0fdf70963061b66308464a18a95e493cc94ad406bbc444f618f562e0f95f276600c27e3ec2269f01504727b0528c7
|
7
|
+
data.tar.gz: 45b2a32802ea5ab504a8c3ee04f714a87b27227ffa66282d64243e3161aa0628001f1925e3ad7aaf09fcd0fbddc4def36e9b9940c76a87b195c2f51b19006bf9
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,29 @@
|
|
2
2
|
|
3
3
|
## master
|
4
4
|
|
5
|
+
## 1.5.0.pre.4 (2023-07-06)
|
6
|
+
|
7
|
+
### Type checker core
|
8
|
+
|
9
|
+
* Fix unreachability test ([#842](https://github.com/soutaro/steep/pull/842))
|
10
|
+
* Make type of `case` node `untyped` rather than `nil` ([#841](https://github.com/soutaro/steep/pull/841))
|
11
|
+
* Fix `#partition_union` ([#840](https://github.com/soutaro/steep/pull/840))
|
12
|
+
* Fix type-case ([#839](https://github.com/soutaro/steep/pull/839))
|
13
|
+
|
14
|
+
## 1.5.0.pre.3 (2023-07-05)
|
15
|
+
|
16
|
+
### Type checker core
|
17
|
+
|
18
|
+
* Resolve type names from TypeAssertion and TypeApplication ([#836](https://github.com/soutaro/steep/pull/836))
|
19
|
+
|
20
|
+
### Commandline tool
|
21
|
+
|
22
|
+
* Replace ElseOnExhaustiveCase by UnreachableBranch from steep/diagnostic/ruby.rb ([#833](https://github.com/soutaro/steep/pull/833))
|
23
|
+
|
24
|
+
### Language server
|
25
|
+
|
26
|
+
* Reuse the latest result to keep SignatureHelp opened while typing ([#835](https://github.com/soutaro/steep/pull/835))
|
27
|
+
|
5
28
|
## 1.5.0.pre.2 (2023-07-05)
|
6
29
|
|
7
30
|
### Language server
|
@@ -21,6 +44,10 @@
|
|
21
44
|
* Fix type assertion parsing error ([#805](https://github.com/soutaro/steep/pull/805))
|
22
45
|
* Distribute `untyped` to block params ([#798](https://github.com/soutaro/steep/pull/798))
|
23
46
|
* Should escape underscore for method name ([#770](https://github.com/soutaro/steep/pull/770))
|
47
|
+
* Give a special typing rule to `#lambda` calls ([#811](https://github.com/soutaro/steep/pull/811))
|
48
|
+
* Support early return code using "and return" ([#828](https://github.com/soutaro/steep/pull/828))
|
49
|
+
* Validate type applications in ancestors ([#810](https://github.com/soutaro/steep/pull/810))
|
50
|
+
* Convert block-pass-arguments with `#to_proc` ([#806](https://github.com/soutaro/steep/pull/806))
|
24
51
|
|
25
52
|
### Commandline tool
|
26
53
|
|
@@ -38,11 +65,14 @@
|
|
38
65
|
|
39
66
|
* Completion in annotations ([#818](https://github.com/soutaro/steep/pull/818))
|
40
67
|
* Implement *go to type definition* ([#784](https://github.com/soutaro/steep/pull/784))
|
68
|
+
* completion: Support completion for optional chaining (&.) ([#827](https://github.com/soutaro/steep/pull/827))
|
69
|
+
* signature helps are not shown if the target code has comments ([#829](https://github.com/soutaro/steep/pull/829))
|
41
70
|
|
42
71
|
### Miscellaneous
|
43
72
|
|
44
73
|
* Typecheck sources ([#820](https://github.com/soutaro/steep/pull/820))
|
45
74
|
* Relax concurrent-ruby requirement ([#812](https://github.com/soutaro/steep/pull/812))
|
75
|
+
* Cast from union for faster type checking ([#830](https://github.com/soutaro/steep/pull/830))
|
46
76
|
|
47
77
|
## 1.4.0 (2023-04-25)
|
48
78
|
|
data/Gemfile.lock
CHANGED
@@ -25,6 +25,8 @@ module Steep
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def types(context, subtyping, type_vars)
|
28
|
+
resolver = RBS::Resolver::TypeNameResolver.new(subtyping.factory.env)
|
29
|
+
|
28
30
|
# @type var types: Array[Types::t]
|
29
31
|
types = []
|
30
32
|
|
@@ -32,6 +34,7 @@ module Steep
|
|
32
34
|
|
33
35
|
while true
|
34
36
|
ty = RBS::Parser.parse_type(loc.buffer, range: loc.range, variables: type_vars) or break
|
37
|
+
ty = ty.map_type_name {|name| resolver.resolve(name, context: context) || name.absolute! }
|
35
38
|
|
36
39
|
validator = Signature::Validator.new(checker: subtyping)
|
37
40
|
validator.validate_type(ty)
|
@@ -41,7 +44,7 @@ module Steep
|
|
41
44
|
end
|
42
45
|
|
43
46
|
ty = subtyping.factory.type(ty)
|
44
|
-
types <<
|
47
|
+
types << ty
|
45
48
|
|
46
49
|
match = RBS::Location.new(loc.buffer, ty.location.end_pos, type_location.end_pos).source.match(/\A\s*,\s*/) or break
|
47
50
|
offset = match.length
|
@@ -18,12 +18,14 @@ module Steep
|
|
18
18
|
|
19
19
|
def type(context, subtyping, type_vars)
|
20
20
|
if ty = RBS::Parser.parse_type(type_location.buffer, range: type_location.range, variables: type_vars, require_eof: true)
|
21
|
+
resolver = RBS::Resolver::TypeNameResolver.new(subtyping.factory.env)
|
22
|
+
ty = ty.map_type_name {|name| resolver.resolve(name, context: context) || name.absolute! }
|
23
|
+
|
21
24
|
validator = Signature::Validator.new(checker: subtyping)
|
22
25
|
validator.validate_type(ty)
|
23
26
|
|
24
27
|
unless validator.has_error?
|
25
|
-
|
26
|
-
subtyping.factory.absolute_type(ty, context: context)
|
28
|
+
subtyping.factory.type(ty)
|
27
29
|
end
|
28
30
|
else
|
29
31
|
nil
|
@@ -358,16 +358,21 @@ module Steep
|
|
358
358
|
partition_union(unfold)
|
359
359
|
end
|
360
360
|
when AST::Types::Union
|
361
|
-
|
362
|
-
|
363
|
-
|
361
|
+
truthy_types = [] #: Array[AST::Types::t]
|
362
|
+
falsy_types = [] #: Array[AST::Types::t]
|
363
|
+
|
364
|
+
type.types.each do |type|
|
365
|
+
truthy, falsy = partition_union(type)
|
366
|
+
|
367
|
+
truthy_types << truthy if truthy
|
368
|
+
falsy_types << falsy if falsy
|
364
369
|
end
|
365
370
|
|
366
371
|
[
|
367
372
|
truthy_types.empty? ? nil : AST::Types::Union.build(types: truthy_types),
|
368
373
|
falsy_types.empty? ? nil : AST::Types::Union.build(types: falsy_types)
|
369
374
|
]
|
370
|
-
when AST::Types::Any, AST::Types::Boolean
|
375
|
+
when AST::Types::Any, AST::Types::Boolean, AST::Types::Top, AST::Types::Logic::Base
|
371
376
|
[type, type]
|
372
377
|
when AST::Types::Nil
|
373
378
|
[nil, type]
|
@@ -968,7 +968,7 @@ module Steep
|
|
968
968
|
{
|
969
969
|
ImplicitBreakValueMismatch => :warning,
|
970
970
|
FallbackAny => :information,
|
971
|
-
|
971
|
+
UnreachableBranch => :warning,
|
972
972
|
UnknownConstant => :warning,
|
973
973
|
MethodDefinitionMissing => :information,
|
974
974
|
FalseAssertion => :information,
|
@@ -989,7 +989,7 @@ module Steep
|
|
989
989
|
NoMethod => nil,
|
990
990
|
ImplicitBreakValueMismatch => nil,
|
991
991
|
FallbackAny => nil,
|
992
|
-
|
992
|
+
UnreachableBranch => nil,
|
993
993
|
UnknownConstant => nil,
|
994
994
|
MethodDefinitionMissing => nil,
|
995
995
|
UnsupportedSyntax => nil,
|
@@ -1006,7 +1006,7 @@ module Steep
|
|
1006
1006
|
NoMethod => nil,
|
1007
1007
|
ImplicitBreakValueMismatch => nil,
|
1008
1008
|
FallbackAny => nil,
|
1009
|
-
|
1009
|
+
UnreachableBranch => nil,
|
1010
1010
|
UnknownConstant => nil,
|
1011
1011
|
MethodDefinitionMissing => nil,
|
1012
1012
|
UnexpectedJump => nil,
|
@@ -406,7 +406,8 @@ module Steep
|
|
406
406
|
)
|
407
407
|
end
|
408
408
|
|
409
|
-
|
409
|
+
@last_signature_help_line = job.line
|
410
|
+
@last_signature_help_result = LSP::Interface::SignatureHelp.new(
|
410
411
|
signatures: signatures,
|
411
412
|
active_signature: index
|
412
413
|
)
|
@@ -414,7 +415,8 @@ module Steep
|
|
414
415
|
end
|
415
416
|
end
|
416
417
|
rescue Parser::SyntaxError
|
417
|
-
#
|
418
|
+
# Reuse the latest result to keep SignatureHelp opened while typing
|
419
|
+
@last_signature_help_result if @last_signature_help_line == job.line
|
418
420
|
end
|
419
421
|
end
|
420
422
|
end
|
@@ -1398,8 +1398,11 @@ module Steep
|
|
1398
1398
|
when :true, :false
|
1399
1399
|
ty = node.type == :true ? AST::Types::Literal.new(value: true) : AST::Types::Literal.new(value: false)
|
1400
1400
|
|
1401
|
-
|
1401
|
+
case
|
1402
|
+
when hint && check_relation(sub_type: ty, super_type: hint).success? && !hint.is_a?(AST::Types::Any) && !hint.is_a?(AST::Types::Top)
|
1402
1403
|
add_typing(node, type: hint)
|
1404
|
+
when condition
|
1405
|
+
add_typing(node, type: ty)
|
1403
1406
|
else
|
1404
1407
|
add_typing(node, type: AST::Types::Boolean.new)
|
1405
1408
|
end
|
@@ -1920,18 +1923,9 @@ module Steep
|
|
1920
1923
|
cond_vars.delete(name)
|
1921
1924
|
end
|
1922
1925
|
|
1923
|
-
var_name = :"_a#{SecureRandom.alphanumeric(4)}"
|
1924
|
-
var_cond, value_node =
|
1925
|
-
|
1926
|
-
unless constr.context.type_env[value_node]
|
1927
|
-
constr = constr.update_type_env do |env|
|
1928
|
-
env.assign_local_variable(var_name, cond_type, nil)
|
1929
|
-
end
|
1930
|
-
cond = var_cond
|
1931
|
-
else
|
1932
|
-
value_node = nil
|
1933
|
-
end
|
1934
|
-
end
|
1926
|
+
var_name = :"_a[#{SecureRandom.alphanumeric(4)}]"
|
1927
|
+
var_cond, value_node = transform_condition_node(cond, var_name)
|
1928
|
+
constr = constr.update_type_env {|env| env.assign_local_variable(var_name, cond_type, nil) }
|
1935
1929
|
|
1936
1930
|
next_branch_reachable = true
|
1937
1931
|
|
@@ -1949,12 +1943,12 @@ module Steep
|
|
1949
1943
|
false_branch_reachable = false
|
1950
1944
|
|
1951
1945
|
tests.each do |test|
|
1952
|
-
test_node = test.updated(:send, [test, :===,
|
1946
|
+
test_node = test.updated(:send, [test, :===, var_cond])
|
1953
1947
|
test_type, test_constr = test_constr.synthesize(test_node, condition: true).to_ary
|
1954
1948
|
truthy, falsy = interpreter.eval(node: test_node, env: test_constr.context.type_env)
|
1955
1949
|
|
1956
|
-
truthy_env = truthy.env
|
1957
|
-
falsy_env = falsy.env
|
1950
|
+
truthy_env = propagate_type_env(var_name, value_node, truthy.env)
|
1951
|
+
falsy_env = propagate_type_env(var_name, value_node, falsy.env)
|
1958
1952
|
|
1959
1953
|
test_envs << truthy_env
|
1960
1954
|
|
@@ -2003,11 +1997,6 @@ module Steep
|
|
2003
1997
|
types = branch_results.map(&:type)
|
2004
1998
|
constrs = branch_results.map(&:constr)
|
2005
1999
|
|
2006
|
-
cond_type = when_constr.context.type_env[var_name]
|
2007
|
-
cond_type ||= when_constr.context.type_env[cond_vars.first || raise] unless cond_vars.empty?
|
2008
|
-
cond_type ||= when_constr.context.type_env[value_node] if value_node
|
2009
|
-
cond_type ||= typing.type_of(node: node.children[0])
|
2010
|
-
|
2011
2000
|
if !next_branch_reachable
|
2012
2001
|
# Exhaustive
|
2013
2002
|
_, _, _, loc = deconstruct_case_node!(node)
|
@@ -2030,9 +2019,6 @@ module Steep
|
|
2030
2019
|
branch_results = [] #: Array[Pair]
|
2031
2020
|
|
2032
2021
|
condition_constr = constr
|
2033
|
-
clause_constr = constr
|
2034
|
-
|
2035
|
-
next_branch_reachable = true
|
2036
2022
|
|
2037
2023
|
whens.each do |when_clause|
|
2038
2024
|
when_clause_constr = condition_constr
|
@@ -2043,7 +2029,6 @@ module Steep
|
|
2043
2029
|
*tests, body = when_clause.children
|
2044
2030
|
|
2045
2031
|
branch_reachable = false
|
2046
|
-
false_branch_reachable = false
|
2047
2032
|
|
2048
2033
|
tests.each do |test|
|
2049
2034
|
test_type, condition_constr = condition_constr.synthesize(test, condition: true)
|
@@ -2054,12 +2039,9 @@ module Steep
|
|
2054
2039
|
condition_constr = condition_constr.update_type_env { falsy_env }
|
2055
2040
|
body_envs << truthy_env
|
2056
2041
|
|
2057
|
-
branch_reachable ||=
|
2058
|
-
false_branch_reachable ||= !falsy.unreachable
|
2042
|
+
branch_reachable ||= !truthy.unreachable
|
2059
2043
|
end
|
2060
2044
|
|
2061
|
-
next_branch_reachable &&= false_branch_reachable
|
2062
|
-
|
2063
2045
|
if body
|
2064
2046
|
branch_results <<
|
2065
2047
|
when_clause_constr
|
@@ -4490,16 +4472,27 @@ module Steep
|
|
4490
4472
|
end
|
4491
4473
|
|
4492
4474
|
def union_type_unify(*types)
|
4493
|
-
types.
|
4494
|
-
unless no_subtyping?(sub_type: type1, super_type: type2)
|
4495
|
-
next type2
|
4496
|
-
end
|
4475
|
+
types = types.reject {|t| t.is_a?(AST::Types::Bot) }
|
4497
4476
|
|
4498
|
-
|
4499
|
-
|
4500
|
-
|
4477
|
+
if types.empty?
|
4478
|
+
AST::Types::Bot.new
|
4479
|
+
else
|
4480
|
+
types.inject do |type1, type2|
|
4481
|
+
next type2 if type1.is_a?(AST::Types::Any)
|
4482
|
+
next type1 if type2.is_a?(AST::Types::Any)
|
4501
4483
|
|
4502
|
-
|
4484
|
+
unless no_subtyping?(sub_type: type1, super_type: type2)
|
4485
|
+
# type1 <: type2
|
4486
|
+
next type2
|
4487
|
+
end
|
4488
|
+
|
4489
|
+
unless no_subtyping?(sub_type: type2, super_type: type1)
|
4490
|
+
# type2 <: type1
|
4491
|
+
next type1
|
4492
|
+
end
|
4493
|
+
|
4494
|
+
union_type(type1, type2)
|
4495
|
+
end
|
4503
4496
|
end
|
4504
4497
|
end
|
4505
4498
|
|
@@ -5029,33 +5022,19 @@ module Steep
|
|
5029
5022
|
with_new_typing(typing.parent || raise)
|
5030
5023
|
end
|
5031
5024
|
|
5032
|
-
def
|
5025
|
+
def transform_condition_node(node, var_name)
|
5033
5026
|
case node.type
|
5034
5027
|
when :lvasgn
|
5035
5028
|
name, rhs = node.children
|
5036
|
-
rhs, value_node =
|
5037
|
-
|
5038
|
-
[node.updated(nil, [name, rhs]), value_node]
|
5039
|
-
else
|
5040
|
-
[node, value_node]
|
5041
|
-
end
|
5029
|
+
rhs, value_node = transform_condition_node(rhs, var_name)
|
5030
|
+
[node.updated(nil, [name, rhs]), value_node]
|
5042
5031
|
when :begin
|
5043
5032
|
*children, last = node.children
|
5044
|
-
last, value_node =
|
5045
|
-
|
5046
|
-
[node.updated(nil, children.push(last)), value_node]
|
5047
|
-
else
|
5048
|
-
[node, value_node]
|
5049
|
-
end
|
5050
|
-
when :lvar
|
5051
|
-
[node, nil]
|
5033
|
+
last, value_node = transform_condition_node(last, var_name)
|
5034
|
+
[node.updated(nil, children.push(last)), value_node]
|
5052
5035
|
else
|
5053
|
-
|
5054
|
-
|
5055
|
-
else
|
5056
|
-
var_node = node.updated(:lvar, [var_name])
|
5057
|
-
[var_node, node]
|
5058
|
-
end
|
5036
|
+
var_node = node.updated(:lvar, [var_name])
|
5037
|
+
[var_node, node]
|
5059
5038
|
end
|
5060
5039
|
end
|
5061
5040
|
|
@@ -5109,5 +5088,20 @@ module Steep
|
|
5109
5088
|
end
|
5110
5089
|
end
|
5111
5090
|
end
|
5091
|
+
|
5092
|
+
def propagate_type_env(source, dest, env)
|
5093
|
+
source_type = env[source] or raise
|
5094
|
+
|
5095
|
+
if dest.type == :lvar
|
5096
|
+
var_name = dest.children[0] #: Symbol
|
5097
|
+
env.assign_local_variable(var_name, source_type, nil)
|
5098
|
+
else
|
5099
|
+
if env[dest]
|
5100
|
+
env.replace_pure_call_type(dest, source_type)
|
5101
|
+
else
|
5102
|
+
env
|
5103
|
+
end
|
5104
|
+
end
|
5105
|
+
end
|
5112
5106
|
end
|
5113
5107
|
end
|
data/lib/steep/version.rb
CHANGED
@@ -52,6 +52,10 @@ module Steep
|
|
52
52
|
|
53
53
|
module LSP = LanguageServer::Protocol
|
54
54
|
|
55
|
+
@last_signature_help_line: Integer
|
56
|
+
|
57
|
+
@last_signature_help_result: LanguageServer::Protocol::Interface::SignatureHelp
|
58
|
+
|
55
59
|
attr_reader service: Services::TypeCheckService
|
56
60
|
|
57
61
|
def initialize: (project: Project, reader: Reader, writer: Writer, ?queue: Queue) -> void
|
@@ -538,18 +538,30 @@ module Steep
|
|
538
538
|
# Returns a pair of transformed node and the outer most call/non-value node if present.
|
539
539
|
#
|
540
540
|
# ```rb
|
541
|
-
# x = y = foo() # Call `#
|
541
|
+
# x = y = foo() # Call `#transform_condition_node` with the node and var_name `:__foo__`
|
542
542
|
# # => Returns [x = y = __foo__, foo()]
|
543
|
+
#
|
544
|
+
# x # Call `#transform_condition_node` with the node and var_name `:__foo__`
|
545
|
+
# # => Returns [__foo__, x]
|
543
546
|
# ```
|
544
547
|
#
|
545
548
|
# This is typically used for transforming assginment node for case condition.
|
546
549
|
#
|
547
|
-
def
|
550
|
+
def transform_condition_node: (Parser::AST::Node node, Symbol) -> [Parser::AST::Node, Parser::AST::Node]
|
548
551
|
|
549
552
|
def type_name: (AST::Types::t) -> RBS::TypeName?
|
550
553
|
|
551
554
|
def singleton_type: (AST::Types::t) -> AST::Types::t?
|
552
555
|
|
553
556
|
def instance_type: (AST::Types::t) -> AST::Types::t?
|
557
|
+
|
558
|
+
# Propagate an entry of `source` in TypeEnv to `dest`
|
559
|
+
#
|
560
|
+
# `source` is name of a local variable.
|
561
|
+
#
|
562
|
+
# If `dest` is a `lvar` node, it updates local variable entry of TypeEnv.
|
563
|
+
# Otherwise, it updates *pure* call of `dest` if it already exists.
|
564
|
+
#
|
565
|
+
def propagate_type_env: (Symbol source, Parser::AST::Node dest, TypeInference::TypeEnv) -> TypeInference::TypeEnv
|
554
566
|
end
|
555
567
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: steep
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.5.0.pre.
|
4
|
+
version: 1.5.0.pre.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Soutaro Matsumoto
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-07-
|
11
|
+
date: 2023-07-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: parser
|