steep 0.31.0 → 0.35.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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -0
  3. data/lib/steep.rb +3 -2
  4. data/lib/steep/annotation_parser.rb +1 -1
  5. data/lib/steep/ast/types/factory.rb +66 -60
  6. data/lib/steep/cli.rb +15 -2
  7. data/lib/steep/drivers/print_project.rb +11 -0
  8. data/lib/steep/drivers/stats.rb +85 -0
  9. data/lib/steep/drivers/vendor.rb +1 -20
  10. data/lib/steep/errors.rb +19 -15
  11. data/lib/steep/interface/method_type.rb +12 -23
  12. data/lib/steep/method_name.rb +28 -0
  13. data/lib/steep/project/completion_provider.rb +24 -15
  14. data/lib/steep/project/dsl.rb +13 -17
  15. data/lib/steep/project/options.rb +4 -4
  16. data/lib/steep/project/source_file.rb +2 -1
  17. data/lib/steep/project/target.rb +19 -10
  18. data/lib/steep/server/interaction_worker.rb +1 -1
  19. data/lib/steep/server/utils.rb +1 -1
  20. data/lib/steep/source.rb +3 -3
  21. data/lib/steep/subtyping/check.rb +30 -16
  22. data/lib/steep/subtyping/variable_occurrence.rb +2 -0
  23. data/lib/steep/type_construction.rb +585 -416
  24. data/lib/steep/type_inference/context.rb +7 -3
  25. data/lib/steep/type_inference/context_array.rb +1 -1
  26. data/lib/steep/type_inference/local_variable_type_env.rb +10 -1
  27. data/lib/steep/type_inference/logic_type_interpreter.rb +6 -0
  28. data/lib/steep/type_inference/method_call.rb +116 -0
  29. data/lib/steep/typing.rb +38 -8
  30. data/lib/steep/version.rb +1 -1
  31. data/smoke/regression/fun.rb +8 -0
  32. data/smoke/regression/fun.rbs +4 -0
  33. data/smoke/regression/range.rb +5 -0
  34. data/steep.gemspec +1 -1
  35. metadata +10 -6
  36. data/lib/steep/ast/buffer.rb +0 -51
  37. data/lib/steep/ast/location.rb +0 -86
@@ -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
@@ -29,7 +29,7 @@ module Steep
29
29
  else
30
30
  ""
31
31
  end
32
- buffer = AST::Buffer.new(name: source.path, content: content)
32
+ buffer = RBS::Buffer.new(name: source.path, content: content)
33
33
  new(buffer: buffer, context: context, range: range || 0..buffer.content.size)
34
34
  end
35
35
 
@@ -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|
@@ -207,6 +207,12 @@ module Steep
207
207
  [type]
208
208
  ]
209
209
 
210
+ when AST::Types::Name::Interface
211
+ [
212
+ [instance_type],
213
+ [type]
214
+ ]
215
+
210
216
  else
211
217
  [
212
218
  [],
@@ -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,6 +20,7 @@ module Steep
20
20
  attr_reader :should_update
21
21
  attr_reader :contexts
22
22
  attr_reader :root_context
23
+ attr_reader :method_calls
23
24
 
24
25
  def initialize(source:, root_context:, parent: nil, parent_last_update: parent&.last_update, contexts: nil)
25
26
  @source = source
@@ -33,6 +34,7 @@ module Steep
33
34
  @typing = {}.compare_by_identity
34
35
  @root_context = root_context
35
36
  @contexts = contexts || TypeInference::ContextArray.from_source(source: source)
37
+ @method_calls = {}.compare_by_identity
36
38
  end
37
39
 
38
40
  def add_error(error)
@@ -46,6 +48,12 @@ module Steep
46
48
  type
47
49
  end
48
50
 
51
+ def add_call(node, call)
52
+ method_calls[node] = call
53
+
54
+ call
55
+ end
56
+
49
57
  def add_context(range, context:)
50
58
  contexts.insert_context(range, context: context)
51
59
  @last_update += 1
@@ -69,6 +77,20 @@ module Steep
69
77
  end
70
78
  end
71
79
 
80
+ def call_of(node:)
81
+ call = method_calls[node]
82
+
83
+ if call
84
+ call
85
+ else
86
+ if parent
87
+ parent.call_of(node: node)
88
+ else
89
+ raise UnknownNodeError.new(:call, node: node)
90
+ end
91
+ end
92
+ end
93
+
72
94
  def add_context_for_node(node, context:)
73
95
  begin_pos = node.loc.expression.begin_pos
74
96
  end_pos = node.loc.expression.end_pos
@@ -76,6 +98,18 @@ module Steep
76
98
  add_context(begin_pos..end_pos, context: context)
77
99
  end
78
100
 
101
+ def block_range(node)
102
+ send_node, args_node, _ = node.children
103
+ begin_pos = if send_node.type != :lambda && args_node.loc.expression
104
+ args_node.loc.expression.end_pos
105
+ else
106
+ node.loc.begin.end_pos
107
+ end
108
+ end_pos = node.loc.end.begin_pos
109
+
110
+ begin_pos..end_pos
111
+ end
112
+
79
113
  def add_context_for_body(node, context:)
80
114
  case node.type
81
115
  when :class
@@ -117,14 +151,8 @@ module Steep
117
151
  add_context(body_begin_pos..body_end_pos, context: context)
118
152
 
119
153
  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)
154
+ range = block_range(node)
155
+ add_context(range, context: context)
128
156
 
129
157
  when :for
130
158
  _, collection, _ = node.children
@@ -191,6 +219,8 @@ module Steep
191
219
 
192
220
  parent.contexts.merge(contexts)
193
221
 
222
+ parent.method_calls.merge!(method_calls)
223
+
194
224
  errors.each do |error|
195
225
  parent.add_error error
196
226
  end
@@ -1,3 +1,3 @@
1
1
  module Steep
2
- VERSION = "0.31.0"
2
+ VERSION = "0.35.0"
3
3
  end
@@ -0,0 +1,8 @@
1
+ class Fun
2
+ def foo(v)
3
+ !v.nil? && foo2(v)
4
+ end
5
+
6
+ def foo2(_)
7
+ end
8
+ end
@@ -0,0 +1,4 @@
1
+ class Fun
2
+ def foo: (Integer?) -> void
3
+ def foo2: (Integer) -> void
4
+ 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
@@ -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.17.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.31.0
4
+ version: 0.35.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-04 00:00:00.000000000 Z
11
+ date: 2020-11-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser
@@ -106,14 +106,14 @@ dependencies:
106
106
  requirements:
107
107
  - - "~>"
108
108
  - !ruby/object:Gem::Version
109
- version: 0.12.0
109
+ version: 0.17.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.17.0
117
117
  description: Gradual Typing for Ruby
118
118
  email:
119
119
  - matsumoto@soutaro.com
@@ -140,9 +140,7 @@ files:
140
140
  - lib/steep/annotation_parser.rb
141
141
  - lib/steep/ast/annotation.rb
142
142
  - lib/steep/ast/annotation/collection.rb
143
- - lib/steep/ast/buffer.rb
144
143
  - lib/steep/ast/builtin.rb
145
- - lib/steep/ast/location.rb
146
144
  - lib/steep/ast/type_params.rb
147
145
  - lib/steep/ast/types.rb
148
146
  - lib/steep/ast/types/any.rb
@@ -172,6 +170,7 @@ files:
172
170
  - lib/steep/drivers/langserver.rb
173
171
  - lib/steep/drivers/print_project.rb
174
172
  - lib/steep/drivers/signature_error_printer.rb
173
+ - lib/steep/drivers/stats.rb
175
174
  - lib/steep/drivers/trace_printer.rb
176
175
  - lib/steep/drivers/utils/driver_helper.rb
177
176
  - lib/steep/drivers/validate.rb
@@ -183,6 +182,7 @@ files:
183
182
  - lib/steep/interface/method.rb
184
183
  - lib/steep/interface/method_type.rb
185
184
  - lib/steep/interface/substitution.rb
185
+ - lib/steep/method_name.rb
186
186
  - lib/steep/module_helper.rb
187
187
  - lib/steep/project.rb
188
188
  - lib/steep/project/completion_provider.rb
@@ -219,6 +219,7 @@ files:
219
219
  - lib/steep/type_inference/local_variable_type_env.rb
220
220
  - lib/steep/type_inference/logic.rb
221
221
  - lib/steep/type_inference/logic_type_interpreter.rb
222
+ - lib/steep/type_inference/method_call.rb
222
223
  - lib/steep/type_inference/send_args.rb
223
224
  - lib/steep/type_inference/type_env.rb
224
225
  - lib/steep/typing.rb
@@ -331,9 +332,12 @@ files:
331
332
  - smoke/regexp/b.rb
332
333
  - smoke/regression/Steepfile
333
334
  - smoke/regression/array.rb
335
+ - smoke/regression/fun.rb
336
+ - smoke/regression/fun.rbs
334
337
  - smoke/regression/hash.rb
335
338
  - smoke/regression/poly_new.rb
336
339
  - smoke/regression/poly_new.rbs
340
+ - smoke/regression/range.rb
337
341
  - smoke/regression/set_divide.rb
338
342
  - smoke/rescue/Steepfile
339
343
  - smoke/rescue/a.rb
@@ -1,51 +0,0 @@
1
- module Steep
2
- module AST
3
- class Buffer
4
- attr_reader :name
5
- attr_reader :content
6
- attr_reader :lines
7
- attr_reader :ranges
8
-
9
- def initialize(name:, content:)
10
- @name = name
11
- @content = content
12
-
13
- @lines = content.split(/\n/, -1)
14
-
15
- @ranges = []
16
- offset = 0
17
- lines.each.with_index do |line, index|
18
- if index == lines.size - 1
19
- ranges << (offset..offset)
20
- else
21
- size = line.size
22
- range = offset..(offset+size)
23
- ranges << range
24
- offset += size+1
25
- end
26
- end
27
- end
28
-
29
- def pos_to_loc(pos)
30
- index = ranges.bsearch_index do |range|
31
- pos <= range.end
32
- end
33
-
34
- if index
35
- [index + 1, pos - ranges[index].begin]
36
- else
37
- [1, pos]
38
- end
39
- end
40
-
41
- def loc_to_pos(loc)
42
- line, column = loc
43
- ranges[line - 1].begin + column
44
- end
45
-
46
- def source(range)
47
- content[range]
48
- end
49
- end
50
- end
51
- end