steep 0.28.0 → 0.32.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +27 -0
  3. data/bin/steep-prof +1 -2
  4. data/lib/steep.rb +5 -3
  5. data/lib/steep/annotation_parser.rb +2 -4
  6. data/lib/steep/ast/builtin.rb +9 -1
  7. data/lib/steep/ast/types/factory.rb +177 -53
  8. data/lib/steep/ast/types/logic.rb +63 -0
  9. data/lib/steep/interface/method_type.rb +14 -4
  10. data/lib/steep/module_helper.rb +25 -0
  11. data/lib/steep/project.rb +25 -0
  12. data/lib/steep/project/completion_provider.rb +57 -58
  13. data/lib/steep/project/file_loader.rb +7 -2
  14. data/lib/steep/project/hover_content.rb +92 -83
  15. data/lib/steep/project/signature_file.rb +33 -0
  16. data/lib/steep/project/{file.rb → source_file.rb} +24 -54
  17. data/lib/steep/project/target.rb +31 -12
  18. data/lib/steep/server/code_worker.rb +30 -46
  19. data/lib/steep/server/interaction_worker.rb +42 -38
  20. data/lib/steep/server/master.rb +13 -30
  21. data/lib/steep/server/utils.rb +46 -13
  22. data/lib/steep/server/worker_process.rb +4 -2
  23. data/lib/steep/signature/validator.rb +3 -3
  24. data/lib/steep/source.rb +58 -1
  25. data/lib/steep/subtyping/check.rb +5 -7
  26. data/lib/steep/subtyping/constraints.rb +8 -0
  27. data/lib/steep/type_construction.rb +204 -207
  28. data/lib/steep/type_inference/constant_env.rb +2 -5
  29. data/lib/steep/type_inference/logic_type_interpreter.rb +225 -0
  30. data/lib/steep/type_inference/type_env.rb +2 -2
  31. data/lib/steep/version.rb +1 -1
  32. data/smoke/toplevel/Steepfile +5 -0
  33. data/smoke/toplevel/a.rb +4 -0
  34. data/smoke/toplevel/a.rbs +3 -0
  35. data/smoke/type_case/a.rb +0 -7
  36. data/steep.gemspec +2 -2
  37. metadata +18 -14
  38. data/lib/steep/ast/method_type.rb +0 -126
  39. data/lib/steep/ast/namespace.rb +0 -80
  40. data/lib/steep/names.rb +0 -86
@@ -6,7 +6,7 @@ module Steep
6
6
  attr_reader :factory
7
7
  attr_reader :table
8
8
 
9
- # ConstantEnv receives an Names::Module as a context, not a Namespace, because this is a simulation of Ruby.
9
+ # ConstantEnv receives an TypeName as a context, not a Namespace, because this is a simulation of Ruby.
10
10
  # Any namespace is a module or class.
11
11
  def initialize(factory:, context:)
12
12
  @cache = {}
@@ -17,10 +17,7 @@ module Steep
17
17
 
18
18
  def lookup(name)
19
19
  cache[name] ||= begin
20
- constant = table.resolve_constant_reference(
21
- factory.type_name_1(name),
22
- context: context.map {|namespace| factory.namespace_1(namespace) }
23
- )
20
+ constant = table.resolve_constant_reference(name, context: context)
24
21
 
25
22
  if constant
26
23
  factory.type(constant.type)
@@ -0,0 +1,225 @@
1
+ module Steep
2
+ module TypeInference
3
+ class LogicTypeInterpreter
4
+ attr_reader :subtyping
5
+ attr_reader :typing
6
+
7
+ def initialize(subtyping:, typing:)
8
+ @subtyping = subtyping
9
+ @typing = typing
10
+ end
11
+
12
+ def factory
13
+ subtyping.factory
14
+ end
15
+
16
+ def guess_type_from_method(node)
17
+ if node.type == :send
18
+ method = node.children[1]
19
+ case method
20
+ when :is_a?, :kind_of?, :instance_of?
21
+ AST::Types::Logic::ReceiverIsArg.new
22
+ when :nil?
23
+ AST::Types::Logic::ReceiverIsNil.new
24
+ when :!
25
+ AST::Types::Logic::Not.new
26
+ when :===
27
+ AST::Types::Logic::ArgIsReceiver.new
28
+ end
29
+ end
30
+ end
31
+
32
+ def eval(env:, type:, node:)
33
+ value_node, vars = decompose_value(node)
34
+
35
+ truthy_env = env
36
+ falsy_env = env
37
+
38
+ if type.is_a?(AST::Types::Any)
39
+ type = guess_type_from_method(node) || type
40
+ end
41
+
42
+ if type.is_a?(AST::Types::Logic::Base)
43
+ vars.each do |var_name|
44
+ truthy_env = truthy_env.assign!(var_name, node: node, type: AST::Builtin.true_type)
45
+ falsy_env = truthy_env.assign!(var_name, node: node, type: AST::Builtin.false_type)
46
+ end
47
+
48
+ case type
49
+ when AST::Types::Logic::ReceiverIsNil
50
+ case value_node.type
51
+ when :send
52
+ receiver = value_node.children[0]
53
+
54
+ if receiver
55
+ _, receiver_vars = decompose_value(receiver)
56
+
57
+ receiver_vars.each do |receiver_var|
58
+ var_type = env[receiver_var]
59
+ truthy_type, falsy_type = factory.unwrap_optional(var_type)
60
+
61
+ truthy_env = truthy_env.assign!(receiver_var, node: node, type: falsy_type || AST::Builtin.nil_type)
62
+ falsy_env = falsy_env.assign!(receiver_var, node: node, type: truthy_type)
63
+ end
64
+ end
65
+ end
66
+ when AST::Types::Logic::ReceiverIsArg
67
+ case value_node.type
68
+ when :send
69
+ receiver, _, arg = value_node.children
70
+
71
+ if receiver
72
+ _, receiver_vars = decompose_value(receiver)
73
+ arg_type = typing.type_of(node: arg)
74
+
75
+ if arg_type.is_a?(AST::Types::Name::Singleton)
76
+ receiver_vars.each do |var_name|
77
+ var_type = env[var_name]
78
+ truthy_type, falsy_type = type_case_select(var_type, arg_type.name)
79
+
80
+ truthy_env = truthy_env.assign!(var_name, node: node, type: truthy_type)
81
+ falsy_env = falsy_env.assign!(var_name, node: node, type: falsy_type)
82
+ end
83
+ end
84
+ end
85
+ end
86
+ when AST::Types::Logic::ArgIsReceiver
87
+ case value_node.type
88
+ when :send
89
+ receiver, _, arg = value_node.children
90
+
91
+ if receiver
92
+ _, arg_vars = decompose_value(arg)
93
+ receiver_type = typing.type_of(node: receiver)
94
+
95
+ if receiver_type.is_a?(AST::Types::Name::Singleton)
96
+ arg_vars.each do |var_name|
97
+ var_type = env[var_name]
98
+ truthy_type, falsy_type = type_case_select(var_type, receiver_type.name)
99
+
100
+ truthy_env = truthy_env.assign!(var_name, node: node, type: truthy_type)
101
+ falsy_env = falsy_env.assign!(var_name, node: node, type: falsy_type)
102
+ end
103
+ end
104
+ end
105
+ end
106
+ when AST::Types::Logic::Not
107
+ receiver, * = value_node.children
108
+ receiver_type = typing.type_of(node: receiver)
109
+ falsy_env, truthy_env = eval(env: env, type: receiver_type, node: receiver)
110
+ end
111
+ else
112
+ _, vars = decompose_value(node)
113
+
114
+ vars.each do |var_name|
115
+ var_type = env[var_name]
116
+ truthy_type, falsy_type = factory.unwrap_optional(var_type)
117
+
118
+ if falsy_type
119
+ truthy_env = truthy_env.assign!(var_name, node: node, type: truthy_type)
120
+ falsy_env = falsy_env.assign!(var_name, node: node, type: falsy_type)
121
+ else
122
+ truthy_env = truthy_env.assign!(var_name, node: node, type: truthy_type)
123
+ falsy_env = falsy_env.assign!(var_name, node: node, type: truthy_type)
124
+ end
125
+ end
126
+ end
127
+
128
+ [truthy_env, falsy_env]
129
+ end
130
+
131
+ def decompose_value(node)
132
+ case node.type
133
+ when :lvar
134
+ [node, Set[node.children[0].name]]
135
+ when :masgn
136
+ lhs, rhs = node.children
137
+ lhs_vars = lhs.children.select {|m| m.type == :lvasgn }.map {|m| m.children[0].name }
138
+ val, vars = decompose_value(rhs)
139
+ [val, vars + lhs_vars]
140
+ when :lvasgn
141
+ var, rhs = node.children
142
+ val, vars = decompose_value(rhs)
143
+ [val, vars + [var.name]]
144
+ when :begin
145
+ decompose_value(node.children.last)
146
+ when :and
147
+ left, right = node.children
148
+ _, left_vars = decompose_value(left)
149
+ val, right_vars = decompose_value(right)
150
+ [val, left_vars + right_vars]
151
+ else
152
+ [node, Set[]]
153
+ end
154
+ end
155
+
156
+ def type_case_select(type, klass)
157
+ truth_types, false_types = type_case_select0(type, klass)
158
+
159
+ [
160
+ AST::Types::Union.build(types: truth_types),
161
+ AST::Types::Union.build(types: false_types)
162
+ ]
163
+ end
164
+
165
+ def type_case_select0(type, klass)
166
+ instance_type = factory.instance_type(klass)
167
+
168
+ case type
169
+ when AST::Types::Union
170
+ truthy_types = []
171
+ falsy_types = []
172
+
173
+ type.types.each do |ty|
174
+ truths, falses = type_case_select0(ty, klass)
175
+
176
+ if truths.empty?
177
+ falsy_types.push(ty)
178
+ else
179
+ truthy_types.push(*truths)
180
+ falsy_types.push(*falses)
181
+ end
182
+ end
183
+
184
+ [truthy_types, falsy_types]
185
+
186
+ when AST::Types::Name::Instance
187
+ relation = Subtyping::Relation.new(sub_type: type, super_type: instance_type)
188
+ if subtyping.check(relation, constraints: Subtyping::Constraints.empty, self_type: AST::Types::Self.new).success?
189
+ [
190
+ [type],
191
+ []
192
+ ]
193
+ else
194
+ [
195
+ [],
196
+ [type]
197
+ ]
198
+ end
199
+
200
+ when AST::Types::Name::Alias
201
+ ty = factory.expand_alias(type)
202
+ type_case_select0(ty, klass)
203
+
204
+ when AST::Types::Any, AST::Types::Top
205
+ [
206
+ [instance_type],
207
+ [type]
208
+ ]
209
+
210
+ when AST::Types::Name::Interface
211
+ [
212
+ [instance_type],
213
+ [type]
214
+ ]
215
+
216
+ else
217
+ [
218
+ [],
219
+ [type]
220
+ ]
221
+ end
222
+ end
223
+ end
224
+ end
225
+ end
@@ -57,7 +57,7 @@ module Steep
57
57
  end
58
58
  end
59
59
 
60
- # @type method assert: (const: Names::Module) { () -> void } -> AST::Type
60
+ # @type method assert: (const: TypeName) { () -> void } -> AST::Type
61
61
  # | (gvar: Symbol) { () -> void } -> AST::Type
62
62
  # | (ivar: Symbol) { () -> void } -> AST::Type
63
63
  def get(const: nil, gvar: nil, ivar: nil)
@@ -98,7 +98,7 @@ module Steep
98
98
  end
99
99
  end
100
100
 
101
- # @type method assign: (const: Names::Module, type: AST::Type) { (Subtyping::Result::Failure | nil) -> void } -> AST::Type
101
+ # @type method assign: (const: TypeName, type: AST::Type) { (Subtyping::Result::Failure | nil) -> void } -> AST::Type
102
102
  # | (gvar: Symbol, type: AST::Type) { (Subtyping::Result::Failure | nil) -> void } -> AST::Type
103
103
  # | (ivar: Symbol, type: AST::Type) { (Subtyping::Result::Failure | nil) -> void } -> AST::Type
104
104
  def assign(const: nil, gvar: nil, ivar: nil, type:, self_type:, &block)
@@ -1,3 +1,3 @@
1
1
  module Steep
2
- VERSION = "0.28.0"
2
+ VERSION = "0.32.0"
3
3
  end
@@ -0,0 +1,5 @@
1
+ target :test do
2
+ typing_options :strict
3
+ check "*.rb"
4
+ signature "*.rbs"
5
+ end
@@ -0,0 +1,4 @@
1
+ # !expects MethodBodyTypeMismatch: method=fizz_buzz, expected=::String, actual=nil
2
+ def fizz_buzz(n)
3
+ nil
4
+ end
@@ -0,0 +1,3 @@
1
+ class Object
2
+ def fizz_buzz: (Integer) -> String
3
+ end
@@ -26,10 +26,3 @@ when String
26
26
  # @type var x: Integer
27
27
  x + 1
28
28
  end
29
-
30
- case x
31
- when Object
32
- # !expects@+2 IncompatibleTypeCase: var_name=x, ::Object <: (::Integer | ::String | ::Symbol)
33
- # !expects NoMethodError: type=::Object, method=foobar
34
- x.foobar
35
- end
@@ -32,7 +32,7 @@ Gem::Specification.new do |spec|
32
32
  spec.add_runtime_dependency "ast_utils", "~> 0.3.0"
33
33
  spec.add_runtime_dependency "activesupport", ">= 5.1"
34
34
  spec.add_runtime_dependency "rainbow", ">= 2.2.2", "< 4.0"
35
- spec.add_runtime_dependency "listen", "~> 3.1"
36
- spec.add_runtime_dependency "language_server-protocol", "~> 3.14.0.2"
35
+ spec.add_runtime_dependency "listen", "~> 3.0"
36
+ spec.add_runtime_dependency "language_server-protocol", "~> 3.15.0.1"
37
37
  spec.add_runtime_dependency "rbs", "~> 0.12.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.28.0
4
+ version: 0.32.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Soutaro Matsumoto
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-09-16 00:00:00.000000000 Z
11
+ date: 2020-10-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser
@@ -78,28 +78,28 @@ dependencies:
78
78
  requirements:
79
79
  - - "~>"
80
80
  - !ruby/object:Gem::Version
81
- version: '3.1'
81
+ version: '3.0'
82
82
  type: :runtime
83
83
  prerelease: false
84
84
  version_requirements: !ruby/object:Gem::Requirement
85
85
  requirements:
86
86
  - - "~>"
87
87
  - !ruby/object:Gem::Version
88
- version: '3.1'
88
+ version: '3.0'
89
89
  - !ruby/object:Gem::Dependency
90
90
  name: language_server-protocol
91
91
  requirement: !ruby/object:Gem::Requirement
92
92
  requirements:
93
93
  - - "~>"
94
94
  - !ruby/object:Gem::Version
95
- version: 3.14.0.2
95
+ version: 3.15.0.1
96
96
  type: :runtime
97
97
  prerelease: false
98
98
  version_requirements: !ruby/object:Gem::Requirement
99
99
  requirements:
100
100
  - - "~>"
101
101
  - !ruby/object:Gem::Version
102
- version: 3.14.0.2
102
+ version: 3.15.0.1
103
103
  - !ruby/object:Gem::Dependency
104
104
  name: rbs
105
105
  requirement: !ruby/object:Gem::Requirement
@@ -143,8 +143,6 @@ files:
143
143
  - lib/steep/ast/buffer.rb
144
144
  - lib/steep/ast/builtin.rb
145
145
  - lib/steep/ast/location.rb
146
- - lib/steep/ast/method_type.rb
147
- - lib/steep/ast/namespace.rb
148
146
  - lib/steep/ast/type_params.rb
149
147
  - lib/steep/ast/types.rb
150
148
  - lib/steep/ast/types/any.rb
@@ -156,6 +154,7 @@ files:
156
154
  - lib/steep/ast/types/instance.rb
157
155
  - lib/steep/ast/types/intersection.rb
158
156
  - lib/steep/ast/types/literal.rb
157
+ - lib/steep/ast/types/logic.rb
159
158
  - lib/steep/ast/types/name.rb
160
159
  - lib/steep/ast/types/nil.rb
161
160
  - lib/steep/ast/types/proc.rb
@@ -184,14 +183,15 @@ files:
184
183
  - lib/steep/interface/method.rb
185
184
  - lib/steep/interface/method_type.rb
186
185
  - lib/steep/interface/substitution.rb
187
- - lib/steep/names.rb
186
+ - lib/steep/module_helper.rb
188
187
  - lib/steep/project.rb
189
188
  - lib/steep/project/completion_provider.rb
190
189
  - lib/steep/project/dsl.rb
191
- - lib/steep/project/file.rb
192
190
  - lib/steep/project/file_loader.rb
193
191
  - lib/steep/project/hover_content.rb
194
192
  - lib/steep/project/options.rb
193
+ - lib/steep/project/signature_file.rb
194
+ - lib/steep/project/source_file.rb
195
195
  - lib/steep/project/target.rb
196
196
  - lib/steep/server/base_worker.rb
197
197
  - lib/steep/server/code_worker.rb
@@ -218,6 +218,7 @@ files:
218
218
  - lib/steep/type_inference/context_array.rb
219
219
  - lib/steep/type_inference/local_variable_type_env.rb
220
220
  - lib/steep/type_inference/logic.rb
221
+ - lib/steep/type_inference/logic_type_interpreter.rb
221
222
  - lib/steep/type_inference/send_args.rb
222
223
  - lib/steep/type_inference/type_env.rb
223
224
  - lib/steep/typing.rb
@@ -347,6 +348,9 @@ files:
347
348
  - smoke/super/Steepfile
348
349
  - smoke/super/a.rb
349
350
  - smoke/super/a.rbs
351
+ - smoke/toplevel/Steepfile
352
+ - smoke/toplevel/a.rb
353
+ - smoke/toplevel/a.rbs
350
354
  - smoke/type_case/Steepfile
351
355
  - smoke/type_case/a.rb
352
356
  - smoke/yield/Steepfile
@@ -359,7 +363,7 @@ metadata:
359
363
  homepage_uri: https://github.com/soutaro/steep
360
364
  source_code_uri: https://github.com/soutaro/steep
361
365
  changelog_uri: https://github.com/soutaro/steep/blob/master/CHANGELOG.md
362
- post_install_message:
366
+ post_install_message:
363
367
  rdoc_options: []
364
368
  require_paths:
365
369
  - lib
@@ -374,8 +378,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
374
378
  - !ruby/object:Gem::Version
375
379
  version: '0'
376
380
  requirements: []
377
- rubygems_version: 3.1.2
378
- signing_key:
381
+ rubygems_version: 3.0.6
382
+ signing_key:
379
383
  specification_version: 4
380
384
  summary: Gradual Typing for Ruby
381
385
  test_files: []
@@ -1,126 +0,0 @@
1
- module Steep
2
- module AST
3
- class MethodType
4
- module Params
5
- class Base
6
- attr_reader :location
7
-
8
- def initialize(location:)
9
- @location = location
10
- end
11
-
12
- def update_location(location)
13
- dup.instance_eval do
14
- @location = location
15
- self
16
- end
17
- end
18
- end
19
-
20
- class Required < Base
21
- attr_reader :type
22
- attr_reader :next_params
23
-
24
- def initialize(location:, type:, next_params: nil)
25
- super(location: location)
26
- @type = type
27
- @next_params = next_params
28
- end
29
- end
30
-
31
- class Optional < Base
32
- attr_reader :type
33
- attr_reader :next_params
34
-
35
- def initialize(location:, type:, next_params: nil)
36
- super(location: location)
37
- @type = type
38
- @next_params = next_params
39
- end
40
- end
41
-
42
- class Rest < Base
43
- attr_reader :type
44
- attr_reader :next_params
45
-
46
- def initialize(location:, type:, next_params: nil)
47
- super(location: location)
48
- @type = type
49
- @next_params = next_params
50
- end
51
- end
52
-
53
- class RequiredKeyword < Base
54
- attr_reader :name
55
- attr_reader :type
56
- attr_reader :next_params
57
-
58
- def initialize(location:, name:, type:, next_params: nil)
59
- super(location: location)
60
- @name = name
61
- @type = type
62
- @next_params = next_params
63
- end
64
- end
65
-
66
- class OptionalKeyword < Base
67
- attr_reader :name
68
- attr_reader :type
69
- attr_reader :next_params
70
-
71
- def initialize(location:, name:, type:, next_params: nil)
72
- super(location: location)
73
- @name = name
74
- @type = type
75
- @next_params = next_params
76
- end
77
- end
78
-
79
- class RestKeyword < Base
80
- attr_reader :type
81
-
82
- def initialize(location:, type:)
83
- super(location: location)
84
- @type = type
85
- end
86
- end
87
- end
88
-
89
- class Block
90
- attr_reader :location
91
- attr_reader :params
92
- attr_reader :return_type
93
- attr_reader :optional
94
-
95
- def initialize(location:, params:, return_type:, optional:)
96
- @location = location
97
- @params = params
98
- @return_type = return_type
99
- @optional = optional
100
- end
101
- end
102
-
103
- attr_reader :location
104
- attr_reader :type_params
105
- attr_reader :params
106
- attr_reader :block
107
- attr_reader :return_type
108
-
109
- def initialize(location:, type_params:, params:, block:, return_type:)
110
- @location = location
111
- @type_params = type_params
112
- @params = params
113
- @block = block
114
- @return_type = return_type
115
- end
116
-
117
- class Super
118
- attr_reader :location
119
-
120
- def initialize(location:)
121
- @location = location
122
- end
123
- end
124
- end
125
- end
126
- end