steep 0.33.0 → 0.38.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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +28 -0
  3. data/lib/steep.rb +9 -0
  4. data/lib/steep/annotation_parser.rb +1 -1
  5. data/lib/steep/ast/types/factory.rb +167 -102
  6. data/lib/steep/ast/types/logic.rb +20 -1
  7. data/lib/steep/ast/types/proc.rb +32 -20
  8. data/lib/steep/cli.rb +15 -2
  9. data/lib/steep/drivers/print_project.rb +11 -0
  10. data/lib/steep/drivers/stats.rb +85 -0
  11. data/lib/steep/drivers/vendor.rb +1 -20
  12. data/lib/steep/errors.rb +38 -15
  13. data/lib/steep/index/rbs_index.rb +334 -0
  14. data/lib/steep/index/signature_symbol_provider.rb +154 -0
  15. data/lib/steep/index/source_index.rb +100 -0
  16. data/lib/steep/interface/block.rb +79 -0
  17. data/lib/steep/interface/function.rb +770 -0
  18. data/lib/steep/interface/method_type.rb +41 -832
  19. data/lib/steep/method_name.rb +28 -0
  20. data/lib/steep/project/completion_provider.rb +24 -15
  21. data/lib/steep/project/dsl.rb +13 -17
  22. data/lib/steep/project/options.rb +4 -4
  23. data/lib/steep/project/source_file.rb +2 -1
  24. data/lib/steep/project/target.rb +19 -10
  25. data/lib/steep/server/interaction_worker.rb +1 -1
  26. data/lib/steep/server/master.rb +5 -1
  27. data/lib/steep/server/signature_worker.rb +63 -6
  28. data/lib/steep/subtyping/check.rb +70 -32
  29. data/lib/steep/subtyping/variable_occurrence.rb +4 -2
  30. data/lib/steep/subtyping/variable_variance.rb +2 -2
  31. data/lib/steep/type_construction.rb +780 -495
  32. data/lib/steep/type_inference/block_params.rb +1 -1
  33. data/lib/steep/type_inference/constant_env.rb +5 -1
  34. data/lib/steep/type_inference/context.rb +7 -3
  35. data/lib/steep/type_inference/local_variable_type_env.rb +10 -1
  36. data/lib/steep/type_inference/logic_type_interpreter.rb +3 -0
  37. data/lib/steep/type_inference/method_call.rb +116 -0
  38. data/lib/steep/typing.rb +46 -10
  39. data/lib/steep/version.rb +1 -1
  40. data/smoke/regression/range.rb +5 -0
  41. data/smoke/tsort/Steepfile +6 -0
  42. data/smoke/tsort/a.rb +15 -0
  43. data/steep.gemspec +1 -1
  44. metadata +17 -6
@@ -134,7 +134,7 @@ module Steep
134
134
  rest = rest_param&.yield_self {|param| param.type.args[0] }
135
135
  end
136
136
 
137
- Interface::Params.new(
137
+ Interface::Function::Params.new(
138
138
  required: leadings,
139
139
  optional: optionals,
140
140
  rest: rest,
@@ -15,9 +15,13 @@ module Steep
15
15
  @table = RBS::ConstantTable.new(builder: factory.definition_builder)
16
16
  end
17
17
 
18
+ def lookup_constant(name)
19
+ table.resolve_constant_reference(name, context: context)
20
+ end
21
+
18
22
  def lookup(name)
19
23
  cache[name] ||= begin
20
- constant = table.resolve_constant_reference(name, context: context)
24
+ constant = lookup_constant(name)
21
25
 
22
26
  if constant
23
27
  factory.type(constant.type)
@@ -80,6 +80,7 @@ module Steep
80
80
  end
81
81
  end
82
82
 
83
+ attr_reader :call_context
83
84
  attr_reader :method_context
84
85
  attr_reader :block_context
85
86
  attr_reader :break_context
@@ -88,7 +89,7 @@ module Steep
88
89
  attr_reader :type_env
89
90
  attr_reader :lvar_env
90
91
 
91
- def initialize(method_context:, block_context:, break_context:, module_context:, self_type:, type_env:, lvar_env:)
92
+ def initialize(method_context:, block_context:, break_context:, module_context:, self_type:, type_env:, lvar_env:, call_context:)
92
93
  @method_context = method_context
93
94
  @block_context = block_context
94
95
  @break_context = break_context
@@ -96,6 +97,7 @@ module Steep
96
97
  @self_type = self_type
97
98
  @type_env = type_env
98
99
  @lvar_env = lvar_env
100
+ @call_context = call_context
99
101
  end
100
102
 
101
103
  def with(method_context: self.method_context,
@@ -104,7 +106,8 @@ module Steep
104
106
  module_context: self.module_context,
105
107
  self_type: self.self_type,
106
108
  type_env: self.type_env,
107
- lvar_env: self.lvar_env)
109
+ lvar_env: self.lvar_env,
110
+ call_context: self.call_context)
108
111
  self.class.new(
109
112
  method_context: method_context,
110
113
  block_context: block_context,
@@ -112,7 +115,8 @@ module Steep
112
115
  module_context: module_context,
113
116
  self_type: self_type,
114
117
  type_env: type_env,
115
- lvar_env: lvar_env
118
+ lvar_env: lvar_env,
119
+ call_context: call_context
116
120
  )
117
121
  end
118
122
  end
@@ -114,7 +114,9 @@ module Steep
114
114
  relation = Subtyping::Relation.new(sub_type: inner_type, super_type: outer_type)
115
115
  constraints = Subtyping::Constraints.new(unknowns: Set.new)
116
116
  subtyping.check(relation, constraints: constraints, self_type: self_type).else do |result|
117
- yield var, outer_type, inner_type, result
117
+ if block_given?
118
+ yield var, outer_type, inner_type, result
119
+ end
118
120
  end
119
121
  end
120
122
  end
@@ -147,6 +149,13 @@ module Steep
147
149
  )
148
150
  end
149
151
 
152
+ def subst(s)
153
+ update(
154
+ declared_types: declared_types.transform_values {|e| e.update(type: e.type.subst(s)) },
155
+ assigned_types: assigned_types.transform_values {|e| e.update(type: e.type.subst(s)) }
156
+ )
157
+ end
158
+
150
159
  def each
151
160
  if block_given?
152
161
  vars.each do |var|
@@ -46,6 +46,9 @@ module Steep
46
46
  end
47
47
 
48
48
  case type
49
+ when AST::Types::Logic::Env
50
+ truthy_env = type.truthy
51
+ falsy_env = type.falsy
49
52
  when AST::Types::Logic::ReceiverIsNil
50
53
  case value_node.type
51
54
  when :send
@@ -0,0 +1,116 @@
1
+ module Steep
2
+ module TypeInference
3
+ class MethodCall
4
+ class MethodDecl
5
+ attr_reader :method_name
6
+ attr_reader :method_def
7
+
8
+ def initialize(method_name:, method_def:)
9
+ @method_name = method_name
10
+ @method_def = method_def
11
+ end
12
+
13
+ def hash
14
+ method_name.hash
15
+ # RBS::MethodType doesn't have #hash
16
+ end
17
+
18
+ def ==(other)
19
+ other.is_a?(MethodDecl) && other.method_name == method_name && other.method_def == method_def
20
+ end
21
+
22
+ alias eql? ==
23
+
24
+ def method_type
25
+ method_def.type
26
+ end
27
+ end
28
+
29
+ MethodContext = Struct.new(:method_name, keyword_init: true) do
30
+ def to_s
31
+ "@#{method_name}"
32
+ end
33
+ end
34
+
35
+ ModuleContext = Struct.new(:type_name, keyword_init: true) do
36
+ def to_s
37
+ "@#{type_name}@"
38
+ end
39
+ end
40
+
41
+ TopLevelContext = Class.new() do
42
+ def to_s
43
+ "@<main>"
44
+ end
45
+ end
46
+
47
+ UnknownContext = Class.new() do
48
+ def to_s
49
+ "@<unknown>"
50
+ end
51
+ end
52
+
53
+
54
+ class Base
55
+ attr_reader :node
56
+ attr_reader :context
57
+ attr_reader :method_name
58
+ attr_reader :return_type
59
+ attr_reader :receiver_type
60
+
61
+ def initialize(node:, context:, method_name:, receiver_type:, return_type:)
62
+ @node = node
63
+ @context = context
64
+ @method_name = method_name
65
+ @receiver_type = receiver_type
66
+ @return_type = return_type
67
+ end
68
+
69
+ def with_return_type(new_type)
70
+ dup.tap do |copy|
71
+ copy.instance_eval do
72
+ @return_type = new_type
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ class Typed < Base
79
+ attr_reader :actual_method_type
80
+ attr_reader :method_decls
81
+
82
+ def initialize(node:, context:, method_name:, receiver_type:, actual_method_type:, method_decls:, return_type: actual_method_type.return_type)
83
+ super(node: node, context: context, method_name: method_name, receiver_type: receiver_type, return_type: return_type)
84
+ @actual_method_type = actual_method_type
85
+ @method_decls = method_decls
86
+ end
87
+ end
88
+
89
+ class Untyped < Base
90
+ def initialize(node:, context:, method_name:)
91
+ super(node: node, context: context, method_name: method_name, receiver_type: AST::Types::Any.new, return_type: AST::Types::Any.new)
92
+ end
93
+ end
94
+
95
+ class NoMethodError < Base
96
+ attr_reader :error
97
+
98
+ def initialize(node:, context:, method_name:, receiver_type:, error:)
99
+ super(node: node, context: context, method_name: method_name, receiver_type: receiver_type, return_type: AST::Types::Any.new)
100
+ @error = error
101
+ end
102
+ end
103
+
104
+ class Error < Base
105
+ attr_reader :errors
106
+ attr_reader :method_decls
107
+
108
+ def initialize(node:, context:, method_name:, receiver_type:, errors:, method_decls: Set[], return_type: AST::Types::Any.new)
109
+ super(node: node, context: context, method_name: method_name, receiver_type: receiver_type, return_type: return_type)
110
+ @method_decls = method_decls
111
+ @errors = errors
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
@@ -20,8 +20,10 @@ module Steep
20
20
  attr_reader :should_update
21
21
  attr_reader :contexts
22
22
  attr_reader :root_context
23
+ attr_reader :method_calls
24
+ attr_reader :source_index
23
25
 
24
- def initialize(source:, root_context:, parent: nil, parent_last_update: parent&.last_update, contexts: nil)
26
+ def initialize(source:, root_context:, parent: nil, parent_last_update: parent&.last_update, contexts: nil, source_index: nil)
25
27
  @source = source
26
28
 
27
29
  @parent = parent
@@ -33,6 +35,9 @@ module Steep
33
35
  @typing = {}.compare_by_identity
34
36
  @root_context = root_context
35
37
  @contexts = contexts || TypeInference::ContextArray.from_source(source: source)
38
+ @method_calls = {}.compare_by_identity
39
+
40
+ @source_index = source_index || Index::SourceIndex.new(source: source)
36
41
  end
37
42
 
38
43
  def add_error(error)
@@ -46,6 +51,12 @@ module Steep
46
51
  type
47
52
  end
48
53
 
54
+ def add_call(node, call)
55
+ method_calls[node] = call
56
+
57
+ call
58
+ end
59
+
49
60
  def add_context(range, context:)
50
61
  contexts.insert_context(range, context: context)
51
62
  @last_update += 1
@@ -69,6 +80,20 @@ module Steep
69
80
  end
70
81
  end
71
82
 
83
+ def call_of(node:)
84
+ call = method_calls[node]
85
+
86
+ if call
87
+ call
88
+ else
89
+ if parent
90
+ parent.call_of(node: node)
91
+ else
92
+ raise UnknownNodeError.new(:call, node: node)
93
+ end
94
+ end
95
+ end
96
+
72
97
  def add_context_for_node(node, context:)
73
98
  begin_pos = node.loc.expression.begin_pos
74
99
  end_pos = node.loc.expression.end_pos
@@ -76,6 +101,18 @@ module Steep
76
101
  add_context(begin_pos..end_pos, context: context)
77
102
  end
78
103
 
104
+ def block_range(node)
105
+ send_node, args_node, _ = node.children
106
+ begin_pos = if send_node.type != :lambda && args_node.loc.expression
107
+ args_node.loc.expression.end_pos
108
+ else
109
+ node.loc.begin.end_pos
110
+ end
111
+ end_pos = node.loc.end.begin_pos
112
+
113
+ begin_pos..end_pos
114
+ end
115
+
79
116
  def add_context_for_body(node, context:)
80
117
  case node.type
81
118
  when :class
@@ -117,14 +154,8 @@ module Steep
117
154
  add_context(body_begin_pos..body_end_pos, context: context)
118
155
 
119
156
  when :block
120
- send_node, args_node, _ = node.children
121
- begin_pos = if send_node.type != :lambda && args_node.loc.expression
122
- args_node.loc.expression.end_pos
123
- else
124
- node.loc.begin.end_pos
125
- end
126
- end_pos = node.loc.end.begin_pos
127
- add_context(begin_pos..end_pos, context: context)
157
+ range = block_range(node)
158
+ add_context(range, context: context)
128
159
 
129
160
  when :for
130
161
  _, collection, _ = node.children
@@ -167,7 +198,8 @@ module Steep
167
198
  child = self.class.new(source: source,
168
199
  parent: self,
169
200
  root_context: root_context,
170
- contexts: TypeInference::ContextArray.new(buffer: contexts.buffer, range: range, context: nil))
201
+ contexts: TypeInference::ContextArray.new(buffer: contexts.buffer, range: range, context: nil),
202
+ source_index: source_index.new_child)
171
203
  @should_update = true
172
204
 
173
205
  if block_given?
@@ -191,9 +223,13 @@ module Steep
191
223
 
192
224
  parent.contexts.merge(contexts)
193
225
 
226
+ parent.method_calls.merge!(method_calls)
227
+
194
228
  errors.each do |error|
195
229
  parent.add_error error
196
230
  end
231
+
232
+ parent.source_index.merge!(source_index)
197
233
  end
198
234
  end
199
235
  end
@@ -1,3 +1,3 @@
1
1
  module Steep
2
- VERSION = "0.33.0"
2
+ VERSION = "0.38.0"
3
3
  end
@@ -0,0 +1,5 @@
1
+ # @type var x: Range[String]
2
+ x = "foo".."bar"
3
+
4
+ # @type var y: Range[String | Integer]
5
+ y = x
@@ -0,0 +1,6 @@
1
+ target :test do
2
+ signature "."
3
+ check "."
4
+
5
+ library "tsort"
6
+ end
@@ -0,0 +1,15 @@
1
+ # ALLOW FAILURE
2
+
3
+ require "tsort"
4
+
5
+ # @type var g: Hash[Integer, Array[Integer]]
6
+ g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}
7
+
8
+ # @type var each_node: ^() { (Integer) -> void } -> void
9
+ each_node = -> (&b) { g.each_key(&b) }
10
+ # @type var each_child: ^(Integer) { (Integer) -> void } -> void
11
+ each_child = -> (n, &b) { g[n].each(&b) }
12
+
13
+ # @type var xs: Array[String]
14
+ # !expects IncompatibleAssignment: lhs_type=::Array[::String], rhs_type=::Array[::Integer]
15
+ xs = TSort.tsort(each_node, each_child)
@@ -34,5 +34,5 @@ Gem::Specification.new do |spec|
34
34
  spec.add_runtime_dependency "rainbow", ">= 2.2.2", "< 4.0"
35
35
  spec.add_runtime_dependency "listen", "~> 3.0"
36
36
  spec.add_runtime_dependency "language_server-protocol", "~> 3.15.0.1"
37
- spec.add_runtime_dependency "rbs", "~> 0.12.0"
37
+ spec.add_runtime_dependency "rbs", ">= 0.20.0"
38
38
  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: 0.33.0
4
+ version: 0.38.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Soutaro Matsumoto
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-10-13 00:00:00.000000000 Z
11
+ date: 2020-12-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser
@@ -104,16 +104,16 @@ dependencies:
104
104
  name: rbs
105
105
  requirement: !ruby/object:Gem::Requirement
106
106
  requirements:
107
- - - "~>"
107
+ - - ">="
108
108
  - !ruby/object:Gem::Version
109
- version: 0.12.0
109
+ version: 0.20.0
110
110
  type: :runtime
111
111
  prerelease: false
112
112
  version_requirements: !ruby/object:Gem::Requirement
113
113
  requirements:
114
- - - "~>"
114
+ - - ">="
115
115
  - !ruby/object:Gem::Version
116
- version: 0.12.0
116
+ version: 0.20.0
117
117
  description: Gradual Typing for Ruby
118
118
  email:
119
119
  - matsumoto@soutaro.com
@@ -170,6 +170,7 @@ files:
170
170
  - lib/steep/drivers/langserver.rb
171
171
  - lib/steep/drivers/print_project.rb
172
172
  - lib/steep/drivers/signature_error_printer.rb
173
+ - lib/steep/drivers/stats.rb
173
174
  - lib/steep/drivers/trace_printer.rb
174
175
  - lib/steep/drivers/utils/driver_helper.rb
175
176
  - lib/steep/drivers/validate.rb
@@ -177,10 +178,16 @@ files:
177
178
  - lib/steep/drivers/watch.rb
178
179
  - lib/steep/drivers/worker.rb
179
180
  - lib/steep/errors.rb
181
+ - lib/steep/index/rbs_index.rb
182
+ - lib/steep/index/signature_symbol_provider.rb
183
+ - lib/steep/index/source_index.rb
184
+ - lib/steep/interface/block.rb
185
+ - lib/steep/interface/function.rb
180
186
  - lib/steep/interface/interface.rb
181
187
  - lib/steep/interface/method.rb
182
188
  - lib/steep/interface/method_type.rb
183
189
  - lib/steep/interface/substitution.rb
190
+ - lib/steep/method_name.rb
184
191
  - lib/steep/module_helper.rb
185
192
  - lib/steep/project.rb
186
193
  - lib/steep/project/completion_provider.rb
@@ -217,6 +224,7 @@ files:
217
224
  - lib/steep/type_inference/local_variable_type_env.rb
218
225
  - lib/steep/type_inference/logic.rb
219
226
  - lib/steep/type_inference/logic_type_interpreter.rb
227
+ - lib/steep/type_inference/method_call.rb
220
228
  - lib/steep/type_inference/send_args.rb
221
229
  - lib/steep/type_inference/type_env.rb
222
230
  - lib/steep/typing.rb
@@ -334,6 +342,7 @@ files:
334
342
  - smoke/regression/hash.rb
335
343
  - smoke/regression/poly_new.rb
336
344
  - smoke/regression/poly_new.rbs
345
+ - smoke/regression/range.rb
337
346
  - smoke/regression/set_divide.rb
338
347
  - smoke/rescue/Steepfile
339
348
  - smoke/rescue/a.rb
@@ -351,6 +360,8 @@ files:
351
360
  - smoke/toplevel/Steepfile
352
361
  - smoke/toplevel/a.rb
353
362
  - smoke/toplevel/a.rbs
363
+ - smoke/tsort/Steepfile
364
+ - smoke/tsort/a.rb
354
365
  - smoke/type_case/Steepfile
355
366
  - smoke/type_case/a.rb
356
367
  - smoke/yield/Steepfile