steep 1.4.0 → 1.5.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.vscode/steep-shared.code-snippets +41 -0
  4. data/CHANGELOG.md +37 -0
  5. data/Gemfile +2 -5
  6. data/Gemfile.lock +20 -17
  7. data/Gemfile.steep +1 -1
  8. data/Gemfile.steep.lock +6 -6
  9. data/Rakefile +198 -0
  10. data/Steepfile +3 -1
  11. data/lib/steep/ast/builtin.rb +9 -7
  12. data/lib/steep/ast/node/type_application.rb +13 -5
  13. data/lib/steep/ast/node/type_assertion.rb +28 -9
  14. data/lib/steep/ast/types/factory.rb +39 -7
  15. data/lib/steep/cli.rb +2 -1
  16. data/lib/steep/diagnostic/deprecated/else_on_exhaustive_case.rb +20 -0
  17. data/lib/steep/diagnostic/lsp_formatter.rb +3 -3
  18. data/lib/steep/diagnostic/ruby.rb +73 -12
  19. data/lib/steep/drivers/annotations.rb +1 -0
  20. data/lib/steep/drivers/check.rb +18 -13
  21. data/lib/steep/drivers/checkfile.rb +1 -1
  22. data/lib/steep/drivers/diagnostic_printer.rb +6 -4
  23. data/lib/steep/drivers/init.rb +2 -1
  24. data/lib/steep/drivers/print_project.rb +3 -1
  25. data/lib/steep/drivers/stats.rb +1 -1
  26. data/lib/steep/drivers/utils/driver_helper.rb +10 -8
  27. data/lib/steep/drivers/utils/jobs_option.rb +6 -1
  28. data/lib/steep/drivers/validate.rb +9 -5
  29. data/lib/steep/drivers/watch.rb +8 -3
  30. data/lib/steep/expectations.rb +144 -75
  31. data/lib/steep/index/signature_symbol_provider.rb +22 -13
  32. data/lib/steep/node_helper.rb +172 -0
  33. data/lib/steep/server/base_worker.rb +2 -1
  34. data/lib/steep/server/change_buffer.rb +17 -15
  35. data/lib/steep/server/interaction_worker.rb +20 -0
  36. data/lib/steep/server/lsp_formatter.rb +20 -1
  37. data/lib/steep/server/master.rb +51 -36
  38. data/lib/steep/server/type_check_worker.rb +18 -2
  39. data/lib/steep/server/worker_process.rb +19 -2
  40. data/lib/steep/services/completion_provider.rb +189 -3
  41. data/lib/steep/services/file_loader.rb +1 -1
  42. data/lib/steep/services/goto_service.rb +123 -27
  43. data/lib/steep/services/signature_help_provider.rb +1 -6
  44. data/lib/steep/signature/validator.rb +6 -1
  45. data/lib/steep/source.rb +165 -108
  46. data/lib/steep/subtyping/check.rb +5 -3
  47. data/lib/steep/subtyping/variable_variance.rb +11 -0
  48. data/lib/steep/thread_waiter.rb +35 -0
  49. data/lib/steep/type_construction.rb +416 -171
  50. data/lib/steep/type_inference/block_params.rb +50 -9
  51. data/lib/steep/type_inference/context.rb +4 -0
  52. data/lib/steep/type_inference/context_array.rb +6 -6
  53. data/lib/steep/type_inference/logic_type_interpreter.rb +202 -68
  54. data/lib/steep/typing.rb +5 -4
  55. data/lib/steep/version.rb +1 -1
  56. data/lib/steep.rb +21 -14
  57. data/sample/Steepfile +1 -0
  58. data/sig/shims/bundler.rbs +3 -0
  59. data/sig/shims/language-server_protocol.rbs +151 -10
  60. data/sig/shims/parser/nodes.rbs +210 -0
  61. data/sig/shims/parser.rbs +10 -0
  62. data/sig/steep/ast/builtin.rbs +2 -2
  63. data/sig/steep/ast/node/type_application.rbs +2 -2
  64. data/sig/steep/ast/node/type_assertion.rbs +8 -2
  65. data/sig/steep/ast/types/factory.rbs +28 -1
  66. data/sig/steep/diagnostic/deprecated/else_on_exhaustive_case.rbs +13 -0
  67. data/sig/steep/diagnostic/lsp_formatter.rbs +5 -2
  68. data/sig/steep/diagnostic/ruby.rbs +76 -6
  69. data/sig/steep/drivers/annotations.rbs +5 -5
  70. data/sig/steep/drivers/check.rbs +11 -11
  71. data/sig/steep/drivers/diagnostic_printer.rbs +9 -9
  72. data/sig/steep/drivers/init.rbs +6 -6
  73. data/sig/steep/drivers/print_project.rbs +4 -4
  74. data/sig/steep/drivers/utils/driver_helper.rbs +8 -6
  75. data/sig/steep/drivers/validate.rbs +4 -4
  76. data/sig/steep/drivers/watch.rbs +1 -1
  77. data/sig/steep/expectations.rbs +72 -0
  78. data/sig/steep/index/signature_symbol_provider.rbs +22 -10
  79. data/sig/steep/interface/block.rbs +2 -0
  80. data/sig/steep/interface/function.rbs +2 -2
  81. data/sig/steep/node_helper.rbs +56 -0
  82. data/sig/steep/path_helper.rbs +1 -1
  83. data/sig/steep/project/options.rbs +1 -1
  84. data/sig/steep/range_extension.rbs +2 -2
  85. data/sig/steep/server/master.rbs +16 -2
  86. data/sig/steep/server/type_check_worker.rbs +5 -1
  87. data/sig/steep/server/worker_process.rbs +5 -1
  88. data/sig/steep/services/completion_provider.rbs +31 -1
  89. data/sig/steep/services/goto_service.rbs +80 -19
  90. data/sig/steep/source.rbs +27 -4
  91. data/sig/steep/subtyping/variable_variance.rbs +9 -9
  92. data/sig/steep/thread_waiter.rbs +13 -0
  93. data/sig/steep/type_construction.rbs +26 -9
  94. data/sig/steep/type_inference/block_params.rbs +13 -1
  95. data/sig/steep/type_inference/context.rbs +5 -1
  96. data/sig/steep/type_inference/context_array.rbs +16 -15
  97. data/sig/steep/type_inference/logic_type_interpreter.rbs +36 -6
  98. data/sig/steep/type_inference/type_env_builder.rbs +4 -0
  99. data/sig/steep/typing.rbs +22 -20
  100. data/sig/steep.rbs +14 -13
  101. data/smoke/and/a.rb +1 -1
  102. data/smoke/and/test_expectations.yml +5 -7
  103. data/smoke/diagnostics/incompatible_annotation.rb +1 -1
  104. data/smoke/diagnostics/test_expectations.yml +2 -2
  105. data/smoke/enumerator/a.rb +0 -7
  106. data/smoke/enumerator/b.rb +0 -2
  107. data/smoke/enumerator/test_expectations.yml +17 -105
  108. data/smoke/lambda/a.rb +0 -5
  109. data/smoke/lambda/test_expectations.yml +0 -22
  110. data/smoke/type_case/test_expectations.yml +10 -0
  111. data/steep.gemspec +2 -2
  112. metadata +16 -9
@@ -13,13 +13,14 @@ module Steep
13
13
  end
14
14
  end
15
15
 
16
- ConstantQuery = Struct.new(:name, :from, keyword_init: true) do
16
+ class ConstantQuery < Struct.new(:name, :from, keyword_init: true)
17
17
  include SourceHelper
18
18
  end
19
- MethodQuery = Struct.new(:name, :from, keyword_init: true) do
19
+ class MethodQuery < Struct.new(:name, :from, keyword_init: true)
20
20
  include SourceHelper
21
21
  end
22
- TypeNameQuery = Struct.new(:name, keyword_init: true)
22
+ class TypeNameQuery < Struct.new(:name, keyword_init: true)
23
+ end
23
24
 
24
25
  attr_reader :type_check, :assignment
25
26
 
@@ -33,9 +34,7 @@ module Steep
33
34
  end
34
35
 
35
36
  def implementation(path:, line:, column:)
36
- locations = []
37
-
38
- # relative_path = project.relative_path(path)
37
+ locations = [] #: Array[loc]
39
38
 
40
39
  queries = query_at(path: path, line: line, column: column)
41
40
  queries.uniq!
@@ -55,7 +54,7 @@ module Steep
55
54
  end
56
55
 
57
56
  def definition(path:, line:, column:)
58
- locations = []
57
+ locations = [] #: Array[loc]
59
58
 
60
59
  queries = query_at(path: path, line: line, column: column)
61
60
  queries.uniq!
@@ -90,6 +89,61 @@ module Steep
90
89
  end
91
90
  end
92
91
 
92
+ def type_definition(path:, line:, column:)
93
+ locations = [] #: Array[loc]
94
+
95
+ relative_path = project.relative_path(path)
96
+
97
+ target = type_check.source_file?(relative_path) or return []
98
+ source = type_check.source_files[relative_path]
99
+ typing, signature = type_check_path(target: target, path: relative_path, content: source.content, line: line, column: column)
100
+
101
+ typing or return []
102
+ signature or return []
103
+
104
+ node, *_parents = typing.source.find_nodes(line: line, column: column)
105
+ node or return []
106
+
107
+ type = typing.type_of(node: node)
108
+
109
+ subtyping = signature.current_subtyping or return []
110
+
111
+ each_type_name(type).uniq.each do |name|
112
+ type_name_locations(name, locations: locations)
113
+ end
114
+
115
+ locations.uniq.select do |loc|
116
+ case loc
117
+ when RBS::Location
118
+ assignment =~ loc.name
119
+ else
120
+ true
121
+ end
122
+ end
123
+ end
124
+
125
+ def each_type_name(type, &block)
126
+ if block
127
+ case type
128
+ when AST::Types::Name::Instance, AST::Types::Name::Alias, AST::Types::Name::Singleton, AST::Types::Name::Interface
129
+ yield type.name
130
+ when AST::Types::Literal
131
+ yield type.back_type.name
132
+ when AST::Types::Nil
133
+ yield RBS::TypeName.new(name: :NilClass, namespace: RBS::Namespace.root)
134
+ when AST::Types::Boolean
135
+ yield RBS::BuiltinNames::TrueClass.name
136
+ yield RBS::BuiltinNames::FalseClass.name
137
+ end
138
+
139
+ type.each_child do |child|
140
+ each_type_name(child, &block)
141
+ end
142
+ else
143
+ enum_for :each_type_name, type
144
+ end
145
+ end
146
+
93
147
  def test_ast_location(loc, line:, column:)
94
148
  return false if line < loc.line
95
149
  return false if line == loc.line && column < loc.column
@@ -99,7 +153,7 @@ module Steep
99
153
  end
100
154
 
101
155
  def query_at(path:, line:, column:)
102
- queries = []
156
+ queries = [] #: Array[query]
103
157
 
104
158
  relative_path = project.relative_path(path)
105
159
 
@@ -110,29 +164,44 @@ module Steep
110
164
  if typing
111
165
  node, *parents = typing.source.find_nodes(line: line, column: column)
112
166
 
113
- if node
167
+ if node && parents
114
168
  case node.type
115
169
  when :const, :casgn
116
- if test_ast_location(node.location.name, line: line, column: column)
170
+ named_location = (_ = node.location) #: Parser::AST::_NamedLocation
171
+ if test_ast_location(named_location.name, line: line, column: column)
117
172
  if name = typing.source_index.reference(constant_node: node)
118
173
  queries << ConstantQuery.new(name: name, from: :ruby)
119
174
  end
120
175
  end
121
176
  when :def, :defs
122
- if test_ast_location(node.location.name, line: line, column: column)
177
+ named_location = (_ = node.location) #: Parser::AST::_NamedLocation
178
+ if test_ast_location(named_location.name, line: line, column: column)
123
179
  if method_context = typing.context_at(line: line, column: column).method_context
124
- type_name = method_context.method.defined_in
125
- name =
126
- if method_context.method.defs.any? {|defn| defn.member.singleton? }
127
- SingletonMethodName.new(type_name: type_name, method_name: method_context.name)
128
- else
129
- InstanceMethodName.new(type_name: type_name, method_name: method_context.name)
180
+ if method = method_context.method
181
+ method.defs.each do |defn|
182
+ singleton_method =
183
+ case defn.member
184
+ when RBS::AST::Members::MethodDefinition
185
+ defn.member.singleton?
186
+ when RBS::AST::Members::Attribute
187
+ defn.member.kind == :singleton
188
+ end
189
+
190
+ name =
191
+ if singleton_method
192
+ SingletonMethodName.new(type_name: defn.defined_in, method_name: method_context.name)
193
+ else
194
+ InstanceMethodName.new(type_name: defn.defined_in, method_name: method_context.name)
195
+ end
196
+
197
+ queries << MethodQuery.new(name: name, from: :ruby)
130
198
  end
131
- queries << MethodQuery.new(name: name, from: :ruby)
199
+ end
132
200
  end
133
201
  end
134
202
  when :send
135
- if test_ast_location(node.location.selector, line: line, column: column)
203
+ location = (_ = node.location) #: Parser::AST::_SelectorLocation
204
+ if test_ast_location(location.selector, line: line, column: column)
136
205
  if (parent = parents[0]) && parent.type == :block && parent.children[0] == node
137
206
  node = parents[0]
138
207
  end
@@ -161,6 +230,9 @@ module Steep
161
230
 
162
231
  locator = RBS::Locator.new(buffer: buffer, dirs: dirs, decls: decls)
163
232
  last, nodes = locator.find2(line: line, column: column)
233
+
234
+ nodes or raise
235
+
164
236
  case nodes[0]
165
237
  when RBS::AST::Declarations::Class, RBS::AST::Declarations::Module
166
238
  if last == :name
@@ -172,7 +244,8 @@ module Steep
172
244
  end
173
245
  when RBS::AST::Members::MethodDefinition
174
246
  if last == :name
175
- type_name = nodes[1].name
247
+ parent_node = nodes[1] #: RBS::AST::Declarations::Class | RBS::AST::Declarations::Module | RBS::AST::Declarations::Interface
248
+ type_name = parent_node.name
176
249
  method_name = nodes[0].name
177
250
  if nodes[0].instance?
178
251
  queries << MethodQuery.new(
@@ -226,13 +299,19 @@ module Steep
226
299
 
227
300
  case entry = env.constant_entry(name)
228
301
  when RBS::Environment::ConstantEntry
229
- locations << entry.decl.location&.[](:name)
302
+ if entry.decl.location
303
+ locations << entry.decl.location[:name]
304
+ end
230
305
  when RBS::Environment::ClassEntry, RBS::Environment::ModuleEntry
231
306
  entry.decls.each do |d|
232
- locations << d.decl.location&.[](:name)
307
+ if d.decl.location
308
+ locations << d.decl.location[:name]
309
+ end
233
310
  end
234
311
  when RBS::Environment::ClassAliasEntry, RBS::Environment::ModuleAliasEntry
235
- locations << entry.decl.location&.[](:new_name)
312
+ if entry.decl.location
313
+ locations << entry.decl.location[:new_name]
314
+ end
236
315
  end
237
316
  end
238
317
 
@@ -305,11 +384,17 @@ module Steep
305
384
  entry.declarations.each do |decl|
306
385
  case decl
307
386
  when RBS::AST::Members::MethodDefinition
308
- locations << decl.location[:name]
387
+ if decl.location
388
+ locations << decl.location[:name]
389
+ end
309
390
  when RBS::AST::Members::Alias
310
- locations << decl.location[:new_name]
391
+ if decl.location
392
+ locations << decl.location[:new_name]
393
+ end
311
394
  when RBS::AST::Members::AttrAccessor, RBS::AST::Members::AttrReader, RBS::AST::Members::AttrWriter
312
- locations << decl.location[:name]
395
+ if decl.location
396
+ locations << decl.location[:name]
397
+ end
313
398
  end
314
399
  end
315
400
  end
@@ -324,7 +409,18 @@ module Steep
324
409
 
325
410
  entry = index.entry(type_name: name)
326
411
  entry.declarations.each do |decl|
327
- locations << decl.location[:name]
412
+ case decl
413
+ when RBS::AST::Declarations::Class, RBS::AST::Declarations::Module, RBS::AST::Declarations::Interface, RBS::AST::Declarations::TypeAlias
414
+ if decl.location
415
+ locations << decl.location[:name]
416
+ end
417
+ when RBS::AST::Declarations::AliasDecl
418
+ if decl.location
419
+ locations << decl.location[:new_name]
420
+ end
421
+ else
422
+ raise
423
+ end
328
424
  end
329
425
  end
330
426
 
@@ -14,12 +14,7 @@ module Steep
14
14
  def initialize(source:, subtyping:)
15
15
  @source = source
16
16
  @subtyping = subtyping
17
-
18
- text =
19
- if source.node
20
- source.node.loc.expression.source
21
- end
22
- @buffer = RBS::Buffer.new(name: source.path, content: text || "")
17
+ @buffer = source.buffer
23
18
  end
24
19
 
25
20
  def run(line:, column:)
@@ -346,11 +346,12 @@ module Steep
346
346
  end
347
347
 
348
348
  if class_var
349
+ loc = class_var.location #: RBS::Location[untyped, untyped]?
349
350
  @errors << Diagnostic::Signature::ClassVariableDuplicationError.new(
350
351
  class_name: definition.type_name,
351
352
  other_class_name: parent.declared_in,
352
353
  variable_name: name,
353
- location: class_var.location&.[](:name)
354
+ location: loc&.[](:name) || raise
354
355
  )
355
356
  end
356
357
  end
@@ -434,6 +435,10 @@ module Steep
434
435
  ancestor.args,
435
436
  location: location
436
437
  )
438
+
439
+ ancestor.args.each do |arg|
440
+ validate_type(arg)
441
+ end
437
442
  end
438
443
  end
439
444