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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c6cfc6dc27ad9f1d484bf734c1633319866b9c6f2593237adace2f17562dfe4b
4
- data.tar.gz: 05af58e6372461a82e0cfe3984c9694b51bb706236db7a64302e772f476efd9a
3
+ metadata.gz: cfb1de89ec50042cf06306ab17717671e8b6a8451ea2885b4af8085226f7994e
4
+ data.tar.gz: 1b67eb25821061afe42c8c4dd644b30370e866ac9ef8066cb77031799c981145
5
5
  SHA512:
6
- metadata.gz: b3b5f11e9a138fceb039c2fb7970f4fbb0b27344114427267d8d74dfab0050f299a75ee8ff6a7051ef93c353dd73f7eac74d9994f998a07360a6743e7e76a8cf
7
- data.tar.gz: d75bf5d4329e11ff68f0d61421b3c9c4cf24406959b084b4042e03210477f53469ae02bfd351834c276c9d46c9237bd4a3054a8c5a8b460e9be6f617a64f034b
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
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- steep (1.5.0.pre.2)
4
+ steep (1.5.0.pre.4)
5
5
  activesupport (>= 5.1)
6
6
  concurrent-ruby (>= 1.1.10)
7
7
  csv (>= 3.0.9)
@@ -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 << subtyping.factory.absolute_type(ty, context: context)
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
- ty = subtyping.factory.type(ty)
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
- falsy_types, truthy_types = type.types.partition do |type|
362
- (type.is_a?(AST::Types::Literal) && type.value == false) ||
363
- type.is_a?(AST::Types::Nil)
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
- ElseOnExhaustiveCase => :warning,
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
- ElseOnExhaustiveCase => nil,
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
- ElseOnExhaustiveCase => nil,
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
- LSP::Interface::SignatureHelp.new(
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
- # Ignore syntax error
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
- if hint && check_relation(sub_type: ty, super_type: hint).success? && !hint.is_a?(AST::Types::Any) && !hint.is_a?(AST::Types::Top)
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 = extract_outermost_call(cond, var_name)
1925
- if value_node
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, :===, cond])
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 ||= next_branch_reachable && !truthy.unreachable
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.inject do |type1, type2|
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
- unless no_subtyping?(sub_type: type2, super_type: type1)
4499
- next type1
4500
- end
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
- union_type(type1, type2)
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 extract_outermost_call(node, var_name)
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 = extract_outermost_call(rhs, var_name)
5037
- if value_node
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 = extract_outermost_call(last, var_name)
5045
- if value_node
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
- if value_node?(node)
5054
- [node, nil]
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
@@ -417,6 +417,10 @@ module Steep
417
417
  end
418
418
 
419
419
  [truthy_types, falsy_types]
420
+ when AST::Types::Boolean
421
+ [[arg_type], [arg_type]]
422
+ when AST::Types::Top, AST::Types::Any
423
+ [[arg_type], [arg_type]]
420
424
  else
421
425
  types = [arg_type]
422
426
 
data/lib/steep/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Steep
2
- VERSION = "1.5.0.pre.2"
2
+ VERSION = "1.5.0.pre.4"
3
3
  end
@@ -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 `#transform_value_node` with the node and var_name `:__foo__`
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 extract_outermost_call: (Parser::AST::Node node, Symbol) -> [Parser::AST::Node, Parser::AST::Node?]
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.2
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-05 00:00:00.000000000 Z
11
+ date: 2023-07-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser