steep 1.5.0.pre.2 → 1.5.0.pre.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|