steep 1.9.4 → 1.10.0.pre.1

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +34 -3
  3. data/Steepfile +5 -2
  4. data/lib/steep/annotations_helper.rb +43 -0
  5. data/lib/steep/ast/ignore.rb +3 -4
  6. data/lib/steep/cli.rb +102 -23
  7. data/lib/steep/diagnostic/lsp_formatter.rb +17 -3
  8. data/lib/steep/diagnostic/ruby.rb +75 -0
  9. data/lib/steep/diagnostic/signature.rb +20 -0
  10. data/lib/steep/drivers/check.rb +3 -1
  11. data/lib/steep/drivers/diagnostic_printer/base_formatter.rb +19 -0
  12. data/lib/steep/drivers/diagnostic_printer/code_formatter.rb +95 -0
  13. data/lib/steep/drivers/diagnostic_printer/github_actions_formatter.rb +44 -0
  14. data/lib/steep/drivers/diagnostic_printer.rb +9 -86
  15. data/lib/steep/drivers/langserver.rb +4 -1
  16. data/lib/steep/drivers/worker.rb +2 -0
  17. data/lib/steep/interface/builder.rb +2 -2
  18. data/lib/steep/server/custom_methods.rb +12 -0
  19. data/lib/steep/server/interaction_worker.rb +33 -6
  20. data/lib/steep/server/master.rb +103 -7
  21. data/lib/steep/server/type_check_worker.rb +48 -2
  22. data/lib/steep/server/worker_process.rb +31 -20
  23. data/lib/steep/services/completion_provider.rb +12 -2
  24. data/lib/steep/services/signature_service.rb +2 -2
  25. data/lib/steep/services/type_check_service.rb +22 -7
  26. data/lib/steep/signature/validator.rb +56 -4
  27. data/lib/steep/source.rb +3 -1
  28. data/lib/steep/subtyping/check.rb +22 -16
  29. data/lib/steep/type_construction.rb +153 -34
  30. data/lib/steep/type_inference/case_when.rb +2 -0
  31. data/lib/steep/type_inference/logic_type_interpreter.rb +77 -15
  32. data/lib/steep/type_inference/method_call.rb +5 -3
  33. data/lib/steep/version.rb +1 -1
  34. data/lib/steep.rb +10 -0
  35. data/manual/ruby-diagnostics.md +114 -1
  36. data/sample/Steepfile +0 -2
  37. data/sample/lib/conference.rb +14 -0
  38. data/sample/lib/deprecated.rb +7 -0
  39. data/sample/sig/deprecated.rbs +16 -0
  40. data/steep.gemspec +4 -3
  41. metadata +28 -8
@@ -155,7 +155,6 @@ module Steep
155
155
  definition.methods[method_name]&.yield_self do |method|
156
156
  method.method_types
157
157
  .map {|method_type| checker.factory.method_type(method_type) }
158
- .select {|method_type| method_type.is_a?(Interface::MethodType) }
159
158
  .inject {|t1, t2| t1 + t2}
160
159
  end
161
160
  end
@@ -163,6 +162,18 @@ module Steep
163
162
 
164
163
  method_type = annotation_method_type || definition_method_type
165
164
 
165
+ unless method_type
166
+ if definition
167
+ typing.add_error(
168
+ Diagnostic::Ruby::UndeclaredMethodDefinition.new(method_name: method_name, type_name: definition.type_name, node: node)
169
+ )
170
+ else
171
+ typing.add_error(
172
+ Diagnostic::Ruby::MethodDefinitionInUndeclaredModule.new(method_name: method_name, node: node)
173
+ )
174
+ end
175
+ end
176
+
166
177
  if (annotation_return_type = annots&.return_type) && (method_type_return_type = method_type&.type&.return_type)
167
178
  check_relation(sub_type: annotation_return_type, super_type: method_type_return_type).else do |result|
168
179
  typing.add_error(
@@ -1483,6 +1494,10 @@ module Steep
1483
1494
  Diagnostic::Ruby::UnknownConstant.new(node: name_node, name: name_node.children[1]).class!
1484
1495
  )
1485
1496
  end
1497
+
1498
+ if class_name
1499
+ check_deprecation_constant(class_name, name_node, name_node.location.expression)
1500
+ end
1486
1501
  else
1487
1502
  _, constr = synthesize(name_node)
1488
1503
  end
@@ -1538,6 +1553,10 @@ module Steep
1538
1553
  _, constr, module_name = synthesize_constant_decl(name_node, name_node.children[0], name_node.children[1]) do
1539
1554
  typing.add_error Diagnostic::Ruby::UnknownConstant.new(node: name_node, name: name_node.children[1]).module!
1540
1555
  end
1556
+
1557
+ if module_name
1558
+ check_deprecation_constant(module_name, name_node, name_node.location.expression)
1559
+ end
1541
1560
  else
1542
1561
  _, constr = synthesize(name_node)
1543
1562
  end
@@ -1608,6 +1627,7 @@ module Steep
1608
1627
 
1609
1628
  if name
1610
1629
  typing.source_index.add_reference(constant: name, ref: node)
1630
+ constr.check_deprecation_constant(name, node, node.location.expression)
1611
1631
  end
1612
1632
 
1613
1633
  Pair.new(type: type, constr: constr)
@@ -1626,6 +1646,8 @@ module Steep
1626
1646
 
1627
1647
  if constant_name
1628
1648
  typing.source_index.add_definition(constant: constant_name, definition: node)
1649
+ location = node.location #: Parser::Source::Map & Parser::AST::_Variable
1650
+ constr.check_deprecation_constant(constant_name, node, location.name)
1629
1651
  end
1630
1652
 
1631
1653
  value_type, constr = constr.synthesize(node.children.last, hint: constant_type)
@@ -2015,8 +2037,8 @@ module Steep
2015
2037
  branch_result =
2016
2038
  if body
2017
2039
  when_clause_constr
2018
- .for_branch(body)
2019
2040
  .update_type_env {|env| env.join(*body_envs) }
2041
+ .for_branch(body)
2020
2042
  .tap {|constr| typing.cursor_context.set_node_context(body, constr.context) }
2021
2043
  .synthesize(body, hint: hint)
2022
2044
  else
@@ -2040,14 +2062,16 @@ module Steep
2040
2062
 
2041
2063
  if els
2042
2064
  branch_results << condition_constr.synthesize(els, hint: hint)
2065
+ else
2066
+ branch_results << Pair.new(type: AST::Builtin.nil_type, constr: condition_constr)
2067
+ end
2068
+
2069
+ branch_results.reject! do |result|
2070
+ result.type.is_a?(AST::Types::Bot)
2043
2071
  end
2044
2072
 
2045
2073
  types = branch_results.map(&:type)
2046
2074
  envs = branch_results.map {|result| result.constr.context.type_env }
2047
-
2048
- unless els
2049
- types << AST::Builtin.nil_type
2050
- end
2051
2075
  end
2052
2076
 
2053
2077
  constr = constr.update_type_env do |env|
@@ -2387,6 +2411,9 @@ module Steep
2387
2411
  lhs_type = context.type_env[name]
2388
2412
  rhs_type, constr = synthesize(rhs, hint: lhs_type).to_ary
2389
2413
 
2414
+ location = node.location #: Parser::Source::Map & Parser::AST::_Variable
2415
+ constr.check_deprecation_global(name, node, location.name)
2416
+
2390
2417
  type, constr = constr.gvasgn(node, rhs_type)
2391
2418
 
2392
2419
  constr.add_typing(node, type: type)
@@ -2395,6 +2422,9 @@ module Steep
2395
2422
  when :gvar
2396
2423
  yield_self do
2397
2424
  name = node.children.first
2425
+
2426
+ check_deprecation_global(name, node, node.location.expression)
2427
+
2398
2428
  if type = context.type_env[name]
2399
2429
  add_typing(node, type: type)
2400
2430
  else
@@ -2943,7 +2973,7 @@ module Steep
2943
2973
  nil
2944
2974
  ]
2945
2975
  else
2946
- # No neesting
2976
+ # No nesting
2947
2977
  synthesize_constant(node, nil, constant_name, &block)
2948
2978
  end
2949
2979
  end
@@ -3207,6 +3237,18 @@ module Steep
3207
3237
  end
3208
3238
  end
3209
3239
 
3240
+ def deprecated_send?(call)
3241
+ return unless call.node.type == :send || call.node.type == :csend
3242
+
3243
+ call.method_decls.each do |decl|
3244
+ if pair = AnnotationsHelper.deprecated_annotation?(decl.method_def.each_annotation.to_a)
3245
+ return pair
3246
+ end
3247
+ end
3248
+
3249
+ nil
3250
+ end
3251
+
3210
3252
  def type_send_interface(node, interface:, receiver:, receiver_type:, method_name:, arguments:, block_params:, block_body:, tapp:, hint:)
3211
3253
  method = interface.methods[method_name]
3212
3254
 
@@ -3260,6 +3302,20 @@ module Steep
3260
3302
  end
3261
3303
  end
3262
3304
  end
3305
+
3306
+ if (_, message = deprecated_send?(call))
3307
+ send_node, _ = deconstruct_sendish_and_block_nodes(node)
3308
+ send_node or raise
3309
+ _, _, _, loc = deconstruct_send_node!(send_node)
3310
+
3311
+ constr.typing.add_error(
3312
+ Diagnostic::Ruby::DeprecatedReference.new(
3313
+ node: node,
3314
+ location: loc.selector,
3315
+ message: message
3316
+ )
3317
+ )
3318
+ end
3263
3319
  end
3264
3320
 
3265
3321
  if node.type == :csend || ((node.type == :block || node.type == :numblock) && node.children[0].type == :csend)
@@ -3808,26 +3864,40 @@ module Steep
3808
3864
  if forwarded_args
3809
3865
  method_name or raise "method_name cannot be nil if `forwarded_args` is given, because proc/block doesn't support `...` arg"
3810
3866
 
3811
- (params, block = context.method_context&.forward_arg_type) or raise
3867
+ method_context = context.method_context or raise
3868
+ forward_arg_type = method_context.forward_arg_type
3812
3869
 
3813
- checker.with_context(self_type: self_type, instance_type: context.module_context.instance_type, class_type: context.module_context.module_type, constraints: constraints) do
3814
- result = checker.check_method_params(
3815
- :"... (argument forwarding)",
3816
- Subtyping::Relation.new(
3817
- sub_type: forwarded_args.params,
3818
- super_type: params
3870
+ case forward_arg_type
3871
+ when nil
3872
+ if context.method_context.method_type
3873
+ raise "Method context must have `forwarded_arg_type` if `...` node appears in it"
3874
+ else
3875
+ # Skips type checking forwarded argument because the method type is not given
3876
+ end
3877
+ when true
3878
+ # Skip type checking forwarded argument because the method is untyped function
3879
+ else
3880
+ params, _block = forward_arg_type
3881
+
3882
+ checker.with_context(self_type: self_type, instance_type: context.module_context.instance_type, class_type: context.module_context.module_type, constraints: constraints) do
3883
+ result = checker.check_method_params(
3884
+ :"... (argument forwarding)",
3885
+ Subtyping::Relation.new(
3886
+ sub_type: forwarded_args.params,
3887
+ super_type: params
3888
+ )
3819
3889
  )
3820
- )
3821
3890
 
3822
- if result.failure?
3823
- errors.push(
3824
- Diagnostic::Ruby::IncompatibleArgumentForwarding.new(
3825
- method_name: method_name,
3826
- node: forwarded_args.node,
3827
- params_pair: [params, forwarded_args.params],
3828
- result: result
3891
+ if result.failure?
3892
+ errors.push(
3893
+ Diagnostic::Ruby::IncompatibleArgumentForwarding.new(
3894
+ method_name: method_name,
3895
+ node: forwarded_args.node,
3896
+ params_pair: [params, forwarded_args.params],
3897
+ result: result
3898
+ )
3829
3899
  )
3830
- )
3900
+ end
3831
3901
  end
3832
3902
  end
3833
3903
  end
@@ -4181,18 +4251,29 @@ module Steep
4181
4251
 
4182
4252
  case
4183
4253
  when forwarded_args_node = args.forwarded_args_node
4184
- (_, block = method_context!.forward_arg_type) or raise
4254
+ case forward_arg_type = method_context!.forward_arg_type
4255
+ when nil
4256
+ if method_context!.method_type
4257
+ raise "Method context must have `forwarded_arg_type` if `...` node appears in it"
4258
+ else
4259
+ # Skips type checking forwarded argument because the method type is not given
4260
+ end
4261
+ when true
4262
+ # Skip type checking because it's untyped function
4263
+ else
4264
+ _, block = forward_arg_type
4185
4265
 
4186
- method_block_type = method_type.block&.to_proc_type || AST::Builtin.nil_type
4187
- forwarded_block_type = block&.to_proc_type || AST::Builtin.nil_type
4266
+ method_block_type = method_type.block&.to_proc_type || AST::Builtin.nil_type
4267
+ forwarded_block_type = block&.to_proc_type || AST::Builtin.nil_type
4188
4268
 
4189
- if result = constr.no_subtyping?(sub_type: forwarded_block_type, super_type: method_block_type)
4190
- errors << Diagnostic::Ruby::IncompatibleArgumentForwarding.new(
4191
- method_name: method_name,
4192
- node: forwarded_args_node,
4193
- block_pair: [block, method_type.block],
4194
- result: result
4195
- )
4269
+ if result = constr.no_subtyping?(sub_type: forwarded_block_type, super_type: method_block_type)
4270
+ errors << Diagnostic::Ruby::IncompatibleArgumentForwarding.new(
4271
+ method_name: method_name,
4272
+ node: forwarded_args_node,
4273
+ block_pair: [block, method_type.block],
4274
+ result: result
4275
+ )
4276
+ end
4196
4277
  end
4197
4278
 
4198
4279
  when arg.compatible?
@@ -4440,7 +4521,7 @@ module Steep
4440
4521
 
4441
4522
  param_types = param_types_hash.each.with_object({}) do |pair, hash| #$ Hash[Symbol, [AST::Types::t, AST::Types::t?]]
4442
4523
  name, type = pair
4443
- # skip unamed arguments `*`, `**` and `&`
4524
+ # skip unnamed arguments `*`, `**` and `&`
4444
4525
  next if name.nil?
4445
4526
  hash[name] = [type, nil]
4446
4527
  end
@@ -5166,5 +5247,43 @@ module Steep
5166
5247
  end
5167
5248
  end
5168
5249
  end
5250
+
5251
+ def check_deprecation_global(name, node, location)
5252
+ if global_entry = checker.factory.env.global_decls[name]
5253
+ if (_, message = AnnotationsHelper.deprecated_annotation?(global_entry.decl.annotations))
5254
+ typing.add_error(
5255
+ Diagnostic::Ruby::DeprecatedReference.new(
5256
+ node: node,
5257
+ location: location,
5258
+ message: message
5259
+ )
5260
+ )
5261
+ end
5262
+ end
5263
+ end
5264
+
5265
+ def check_deprecation_constant(name, node, location)
5266
+ entry = checker.builder.factory.env.constant_entry(name)
5267
+
5268
+ annotations =
5269
+ case entry
5270
+ when RBS::Environment::ModuleEntry, RBS::Environment::ClassEntry
5271
+ entry.decls.flat_map { _1.decl.annotations }
5272
+ when RBS::Environment::ConstantEntry, RBS::Environment::ClassAliasEntry, RBS::Environment::ModuleAliasEntry
5273
+ entry.decl.annotations
5274
+ end
5275
+
5276
+ if annotations
5277
+ if (_, message = AnnotationsHelper.deprecated_annotation?(annotations))
5278
+ typing.add_error(
5279
+ Diagnostic::Ruby::DeprecatedReference.new(
5280
+ node: node,
5281
+ location: location,
5282
+ message: message
5283
+ )
5284
+ )
5285
+ end
5286
+ end
5287
+ end
5169
5288
  end
5170
5289
  end
@@ -243,6 +243,8 @@ module Steep
243
243
  end
244
244
  end
245
245
 
246
+ results.reject! { _1.type.is_a?(AST::Types::Bot) }
247
+
246
248
  types = results.map {|result| result.type }
247
249
  envs = results.map {|result| result.env }
248
250
 
@@ -169,25 +169,45 @@ module Steep
169
169
  return [truthy_result, falsy_result]
170
170
  end
171
171
  else
172
- if env[node]
173
- truthy_type, falsy_type = factory.partition_union(type)
172
+ receiver, *_ = node.children
173
+ receiver_type = typing.type_of(node: receiver) if receiver
174
+
175
+ if env[receiver] && receiver_type.is_a?(AST::Types::Union)
176
+ result = evaluate_union_method_call(node: node, type: type, env: env, receiver: receiver, receiver_type: receiver_type)
177
+ if result
178
+ truthy_result = result[0] unless result[0].unreachable
179
+ falsy_result = result[1] unless result[1].unreachable
180
+ end
181
+ end
174
182
 
175
- truthy_result =
176
- if truthy_type
177
- Result.new(type: truthy_type, env: env.refine_types(pure_call_types: { node => truthy_type }), unreachable: false)
178
- else
179
- Result.new(type: type, env: env, unreachable: true)
180
- end
183
+ truthy_result ||= Result.new(type: type, env: env, unreachable: false)
184
+ falsy_result ||= Result.new(type: type, env: env, unreachable: false)
181
185
 
182
- falsy_result =
183
- if falsy_type
184
- Result.new(type: falsy_type, env: env.refine_types(pure_call_types: { node => falsy_type }), unreachable: false)
185
- else
186
- Result.new(type: type, env: env, unreachable: true)
187
- end
186
+ truthy_type, falsy_type = factory.partition_union(type)
188
187
 
189
- return [truthy_result, falsy_result]
188
+ if truthy_type
189
+ truthy_result = truthy_result.update_type { truthy_type }
190
+ else
191
+ truthy_result = truthy_result.update_type { BOT }.unreachable!
190
192
  end
193
+
194
+ if falsy_type
195
+ falsy_result = falsy_result.update_type { falsy_type }
196
+ else
197
+ falsy_result = falsy_result.update_type { BOT }.unreachable!
198
+ end
199
+
200
+ if truthy_result.env[node] && falsy_result.env[node]
201
+ if truthy_type
202
+ truthy_result = Result.new(type: truthy_type, env: truthy_result.env.refine_types(pure_call_types: { node => truthy_type }), unreachable: false)
203
+ end
204
+
205
+ if falsy_type
206
+ falsy_result = Result.new(type: falsy_type, env: falsy_result.env.refine_types(pure_call_types: { node => falsy_type }), unreachable: false)
207
+ end
208
+ end
209
+
210
+ return [truthy_result, falsy_result]
191
211
  end
192
212
  end
193
213
 
@@ -408,6 +428,48 @@ module Steep
408
428
  end
409
429
  end
410
430
 
431
+ def evaluate_union_method_call(node:, type:, env:, receiver:, receiver_type:)
432
+ call_type = typing.call_of(node: node) rescue nil
433
+ return unless call_type.is_a?(Steep::TypeInference::MethodCall::Typed)
434
+
435
+ truthy_types = [] #: Array[AST::Types::t]
436
+ falsy_types = [] #: Array[AST::Types::t]
437
+
438
+ receiver_type.types.each do |type|
439
+ if shape = subtyping.builder.shape(type, config)
440
+ method = shape.methods[call_type.method_name] or raise
441
+ method_type = method.method_types.find do |method_type|
442
+ call_type.method_decls.any? {|decl| factory.method_type(decl.method_type) == method_type }
443
+ end
444
+ if method_type
445
+ return_type = method_type.type.return_type
446
+ truthy, falsy = factory.partition_union(return_type)
447
+ truthy_types << type if truthy
448
+ falsy_types << type if falsy
449
+ next
450
+ end
451
+ end
452
+
453
+ truthy_types << type
454
+ falsy_types << type
455
+ end
456
+
457
+ truthy_type = truthy_types.empty? ? BOT : AST::Types::Union.build(types: truthy_types)
458
+ falsy_type = falsy_types.empty? ? BOT : AST::Types::Union.build(types: falsy_types)
459
+
460
+ truthy_env, falsy_env = refine_node_type(
461
+ env: env,
462
+ node: receiver,
463
+ truthy_type: truthy_type,
464
+ falsy_type: falsy_type
465
+ )
466
+
467
+ return [
468
+ Result.new(type: type, env: truthy_env, unreachable: truthy_type.nil?),
469
+ Result.new(type: type, env: falsy_env, unreachable: falsy_type.nil?)
470
+ ]
471
+ end
472
+
411
473
  def decompose_value(node)
412
474
  case node.type
413
475
  when :lvar
@@ -124,12 +124,14 @@ module Steep
124
124
 
125
125
  def pure?
126
126
  method_decls.all? do |method_decl|
127
- case member = method_decl.method_def.member
128
- when RBS::AST::Members::MethodDefinition
129
- member.annotations.any? {|annotation| annotation.string == "pure" }
127
+ case method_decl.method_def.member
130
128
  when RBS::AST::Members::Attribute
131
129
  # The attribute writer is not pure
132
130
  !method_decl.method_name.method_name.end_with?("=")
131
+ else
132
+ method_decl.method_def.each_annotation.any? do |annotation|
133
+ annotation.string == "pure"
134
+ end
133
135
  end
134
136
  end
135
137
  end
data/lib/steep/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Steep
2
- VERSION = "1.9.4"
2
+ VERSION = "1.10.0.pre.1"
3
3
  end
data/lib/steep.rb CHANGED
@@ -17,6 +17,7 @@ require "yaml"
17
17
  require "securerandom"
18
18
  require "base64"
19
19
  require "time"
20
+ require 'socket'
20
21
 
21
22
  require "concurrent/utility/processor_counter"
22
23
  require "terminal-table"
@@ -150,6 +151,11 @@ require "steep/drivers/init"
150
151
  require "steep/drivers/vendor"
151
152
  require "steep/drivers/worker"
152
153
  require "steep/drivers/diagnostic_printer"
154
+ require "steep/drivers/diagnostic_printer/base_formatter"
155
+ require "steep/drivers/diagnostic_printer/code_formatter"
156
+ require "steep/drivers/diagnostic_printer/github_actions_formatter"
157
+
158
+ require "steep/annotations_helper"
153
159
 
154
160
  if ENV["NO_COLOR"]
155
161
  Rainbow.enabled = false
@@ -226,6 +232,10 @@ module Steep
226
232
  end
227
233
  end
228
234
 
235
+ def self.can_fork?
236
+ defined?(fork)
237
+ end
238
+
229
239
  class Sampler
230
240
  def initialize()
231
241
  @samples = []
@@ -40,7 +40,7 @@ A type annotation has a syntax error.
40
40
  ### Ruby code
41
41
 
42
42
  ```ruby
43
- # @type var foo: () ->
43
+ # @type var foo: () ->
44
44
  ```
45
45
 
46
46
  ### Diagnostic
@@ -237,6 +237,52 @@ test.rb:4:6: [error] ::Kernel is declared as a module in RBS
237
237
  | - | - | - | - | - |
238
238
  | error | error | error | - | - |
239
239
 
240
+ <a name='Ruby::DeprecatedReference'></a>
241
+ ## Ruby::DeprecatedReference
242
+
243
+ Method call or constant reference is deprecated.
244
+
245
+ ### RBS
246
+
247
+ ```rbs
248
+ %a{deprecated} class Foo end
249
+
250
+ class Bar
251
+ %a{deprecated: since v0.9} def self.bar: () -> void
252
+ end
253
+ ```
254
+
255
+ ### Ruby code
256
+
257
+ ```ruby
258
+ Foo
259
+
260
+ Bar.bar()
261
+ ```
262
+
263
+ ### Diagnostic
264
+
265
+ ```
266
+ lib/deprecated.rb:1:0: [warning] The constant is deprecated
267
+ │ Diagnostic ID: Ruby::DeprecatedReference
268
+
269
+ └ Foo
270
+ ~~~
271
+
272
+ lib/deprecated.rb:3:4: [warning] The method is deprecated: since v0.9
273
+ │ Diagnostic ID: Ruby::DeprecatedReference
274
+
275
+ └ Bar.bar()
276
+ ~~~
277
+ ```
278
+
279
+
280
+ ### Severity
281
+
282
+ | all_error | strict | default | lenient | silent |
283
+ | - | - | - | - | - |
284
+ | error | warning | warning | warning | - |
285
+
240
286
  <a name='Ruby::DifferentMethodParameterKind'></a>
241
287
  ## Ruby::DifferentMethodParameterKind
242
288
 
@@ -703,6 +749,36 @@ test.rb:2:6: [error] Cannot allow method body have type `::Integer` because decl
703
749
  | - | - | - | - | - |
704
750
  | error | error | error | warning | - |
705
751
 
752
+ <a name='Ruby::MethodDefinitionInUndeclaredModule'></a>
753
+ ## Ruby::MethodDefinitionInUndeclaredModule
754
+
755
+ A `def` syntax doesn't have method type because the module/class is undefined in RBS.
756
+
757
+ ### Ruby code
758
+
759
+ ```ruby
760
+ class UndeclaredClass
761
+ def to_s = 123
762
+ end
763
+ ```
764
+
765
+ ### Diagnostic
766
+
767
+ ```
768
+ test.rb:2:6: [error] Method `to_s` is defined in undeclared module
769
+ │ Diagnostic ID: Ruby::MethodDefinitionInUndeclaredModule
770
+
771
+ └ def to_s = 123
772
+ ~~~~
773
+ ```
774
+
775
+
776
+ ### Severity
777
+
778
+ | all_error | strict | default | lenient | silent |
779
+ | - | - | - | - | - |
780
+ | error | warning | information | hint | - |
781
+
706
782
  <a name='Ruby::MethodDefinitionMissing'></a>
707
783
  ## Ruby::MethodDefinitionMissing
708
784
 
@@ -1235,6 +1311,43 @@ test.rb:2:4: [error] Empty hash doesn't have type annotation
1235
1311
  | - | - | - | - | - |
1236
1312
  | error | error | warning | hint | - |
1237
1313
 
1314
+ <a name='Ruby::UndeclaredMethodDefinition'></a>
1315
+ ## Ruby::UndeclaredMethodDefinition
1316
+
1317
+ A `def` syntax doesn't have corresponding RBS method definition.
1318
+
1319
+ ### RBS
1320
+
1321
+ ```rbs
1322
+ class Foo
1323
+ end
1324
+ ```
1325
+
1326
+ ### Ruby code
1327
+
1328
+ ```ruby
1329
+ class Foo
1330
+ def undeclared = nil
1331
+ end
1332
+ ```
1333
+
1334
+ ### Diagnostic
1335
+
1336
+ ```
1337
+ test.rb:2:6: [error] Method `::Foo#undeclared` is not declared in RBS
1338
+ │ Diagnostic ID: Ruby::UndeclaredMethodDefinition
1339
+
1340
+ └ def undeclared = nil
1341
+ ~~~~~~~~~~
1342
+ ```
1343
+
1344
+
1345
+ ### Severity
1346
+
1347
+ | all_error | strict | default | lenient | silent |
1348
+ | - | - | - | - | - |
1349
+ | error | warning | warning | information | - |
1350
+
1238
1351
  <a name='Ruby::UnexpectedBlockGiven'></a>
1239
1352
  ## Ruby::UnexpectedBlockGiven
1240
1353
 
data/sample/Steepfile CHANGED
@@ -5,8 +5,6 @@ target :lib do
5
5
 
6
6
  check "lib" # Directory name
7
7
 
8
- library "rbs"
9
-
10
8
  # configure_code_diagnostics(D::Ruby.strict) # `strict` diagnostics setting
11
9
  # configure_code_diagnostics(D::Ruby.lenient) # `lenient` diagnostics setting
12
10
  # configure_code_diagnostics(D::Ruby.silent) # `silent` diagnostics setting
@@ -7,19 +7,33 @@ class Conference
7
7
  @title = title
8
8
  @year = year
9
9
  end
10
+
11
+ def hello_world
12
+
13
+ end
10
14
  end
11
15
 
12
16
  Conference.new()
13
17
 
14
18
  Konference.new()
15
19
 
20
+ class Hogehogehoge
21
+ def to_s = 123
16
22
 
23
+ def foo = 23
24
+ end
17
25
 
18
26
  # @type var foo: Konference
19
27
 
20
28
  foo = Conference.new
21
29
 
30
+ class Conference
31
+ def hello = 123
32
+ end
33
+
22
34
  class Conference12
35
+ def hello = 123
36
+
23
37
  class Integer
24
38
  end
25
39
  end
@@ -0,0 +1,7 @@
1
+ Foo
2
+
3
+ Bar.bar()
4
+
5
+ Bar.new.hogehoge("")
6
+
7
+ foo = nil #: Foo