steep 0.31.0 → 0.35.0

Sign up to get free protection for your applications and to get access to all the features.
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