steep 0.49.1 → 0.52.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 +22 -0
  3. data/Gemfile +4 -1
  4. data/Gemfile.lock +8 -5
  5. data/lib/steep/ast/annotation/collection.rb +10 -8
  6. data/lib/steep/ast/types/factory.rb +5 -5
  7. data/lib/steep/cli.rb +83 -1
  8. data/lib/steep/diagnostic/deprecated/unknown_constant_assigned.rb +28 -0
  9. data/lib/steep/diagnostic/ruby.rb +21 -15
  10. data/lib/steep/drivers/check.rb +1 -0
  11. data/lib/steep/drivers/langserver.rb +2 -2
  12. data/lib/steep/drivers/stats.rb +1 -0
  13. data/lib/steep/drivers/utils/jobs_count.rb +1 -1
  14. data/lib/steep/drivers/watch.rb +1 -1
  15. data/lib/steep/index/source_index.rb +18 -1
  16. data/lib/steep/interface/function.rb +5 -0
  17. data/lib/steep/module_helper.rb +4 -7
  18. data/lib/steep/project.rb +15 -1
  19. data/lib/steep/server/interaction_worker.rb +47 -4
  20. data/lib/steep/server/master.rb +10 -5
  21. data/lib/steep/server/type_check_worker.rb +19 -4
  22. data/lib/steep/server/worker_process.rb +15 -6
  23. data/lib/steep/services/completion_provider.rb +109 -1
  24. data/lib/steep/services/goto_service.rb +23 -10
  25. data/lib/steep/services/hover_content.rb +52 -4
  26. data/lib/steep/services/type_check_service.rb +6 -3
  27. data/lib/steep/source.rb +71 -18
  28. data/lib/steep/type_construction.rb +209 -162
  29. data/lib/steep/type_inference/constant_env.rb +33 -15
  30. data/lib/steep/type_inference/context.rb +6 -7
  31. data/lib/steep/type_inference/type_env.rb +16 -54
  32. data/lib/steep/version.rb +1 -1
  33. data/smoke/const/test_expectations.yml +24 -19
  34. data/smoke/diagnostics/test_expectations.yml +77 -17
  35. data/smoke/integer/test_expectations.yml +24 -4
  36. data/smoke/method/test_expectations.yml +30 -0
  37. data/smoke/regression/test_expectations.yml +24 -0
  38. data/smoke/yield/test_expectations.yml +20 -0
  39. data/steep.gemspec +1 -1
  40. metadata +5 -4
@@ -130,9 +130,8 @@ module Steep
130
130
  end
131
131
 
132
132
  def for_new_method(method_name, node, args:, self_type:, definition:)
133
- annots = source.annotations(block: node, factory: checker.factory, current_module: current_namespace)
134
- type_env = TypeInference::TypeEnv.new(subtyping: checker,
135
- const_env: module_context&.const_env || self.type_env.const_env)
133
+ annots = source.annotations(block: node, factory: checker.factory, context: nesting)
134
+ type_env = TypeInference::TypeEnv.new(subtyping: checker, const_env: module_context&.const_env || self.type_env.const_env)
136
135
 
137
136
  self.type_env.const_types.each do |name, type|
138
137
  type_env.set(const: name, type: type)
@@ -285,17 +284,9 @@ module Steep
285
284
  end
286
285
  end
287
286
  else
288
- name = nil
289
- name ||= absolute_name(module_name).yield_self do |absolute_name|
290
- absolute_name if checker.factory.class_name?(absolute_name) || checker.factory.module_name?(absolute_name)
291
- end
292
- name ||= super_name && absolute_name(super_name).yield_self do |absolute_name|
293
- absolute_name if checker.factory.class_name?(absolute_name) || checker.factory.module_name?(absolute_name)
294
- end
287
+ name = module_name || super_name
295
288
 
296
- if name
297
- absolute_name_ = name
298
- entry = checker.factory.env.class_decls[absolute_name_]
289
+ if name && entry = checker.factory.env.class_decls[name]
299
290
  AST::Annotation::Implements::Module.new(
300
291
  name: name,
301
292
  args: entry.type_params.each.map(&:name)
@@ -304,9 +295,9 @@ module Steep
304
295
  end
305
296
  end
306
297
 
307
- def default_module_context(implement_module_name, const_env:, current_namespace:)
298
+ def default_module_context(implement_module_name, const_env:)
308
299
  if implement_module_name
309
- module_name = checker.factory.absolute_type_name(implement_module_name.name, namespace: current_namespace)
300
+ module_name = checker.factory.absolute_type_name(implement_module_name.name, context: const_env.context)
310
301
  module_args = implement_module_name.args.map {|name| AST::Types::Var.new(name: name) }
311
302
 
312
303
  instance_def = checker.factory.definition_builder.build_instance(module_name)
@@ -319,7 +310,6 @@ module Steep
319
310
  instance_type: instance_type,
320
311
  module_type: module_type,
321
312
  implement_name: implement_module_name,
322
- current_namespace: current_namespace,
323
313
  const_env: const_env,
324
314
  class_name: module_name,
325
315
  instance_definition: instance_def,
@@ -330,7 +320,6 @@ module Steep
330
320
  instance_type: nil,
331
321
  module_type: nil,
332
322
  implement_name: nil,
333
- current_namespace: current_namespace,
334
323
  const_env: self.module_context.const_env,
335
324
  class_name: self.module_context.class_name,
336
325
  module_definition: nil,
@@ -339,17 +328,19 @@ module Steep
339
328
  end
340
329
  end
341
330
 
342
- def for_module(node)
343
- new_module_name = module_name_from_node(node.children.first) or raise "Unexpected module name: #{node.children.first}"
344
- new_namespace = nested_namespace_for_module(new_module_name)
331
+ def for_module(node, new_module_name)
332
+ new_nesting = [nesting, new_module_name || false]
345
333
 
346
- const_context = [new_namespace] + self.module_context.const_env.context
347
- module_const_env = TypeInference::ConstantEnv.new(factory: checker.factory, context: const_context)
334
+ module_const_env = TypeInference::ConstantEnv.new(
335
+ factory: checker.factory,
336
+ context: new_nesting,
337
+ resolver: self.module_context.const_env.resolver
338
+ )
348
339
 
349
- annots = source.annotations(block: node, factory: checker.factory, current_module: new_namespace)
340
+ annots = source.annotations(block: node, factory: checker.factory, context: new_nesting)
350
341
 
351
342
  implement_module_name = implement_module(module_name: new_module_name, annotations: annots)
352
- module_context = default_module_context(implement_module_name, const_env: module_const_env, current_namespace: new_namespace)
343
+ module_context = default_module_context(implement_module_name, const_env: module_const_env)
353
344
 
354
345
  unless implement_module_name
355
346
  module_context = module_context.update(
@@ -446,25 +437,25 @@ module Steep
446
437
  )
447
438
  end
448
439
 
449
- def with_module_constr(node)
450
- constr = for_module(node)
440
+ def with_module_constr(node, module_name)
441
+ constr = for_module(node, module_name)
451
442
  constr.checker.push_variable_bounds(constr.variable_context.upper_bounds) do
452
443
  yield constr
453
444
  end
454
445
  end
455
446
 
456
- def for_class(node)
457
- new_class_name = module_name_from_node(node.children.first) or raise "Unexpected class name: #{node.children.first}"
458
- super_class_name = node.children[1] && module_name_from_node(node.children[1])
459
- new_namespace = nested_namespace_for_module(new_class_name)
460
-
461
- annots = source.annotations(block: node, factory: checker.factory, current_module: new_namespace)
447
+ def for_class(node, new_class_name, super_class_name)
448
+ new_nesting = [nesting, new_class_name || false]
449
+ annots = source.annotations(block: node, factory: checker.factory, context: new_nesting)
462
450
 
463
- const_context = [new_namespace] + self.module_context.const_env.context
464
- class_const_env = TypeInference::ConstantEnv.new(factory: checker.factory, context: const_context)
451
+ class_const_env = TypeInference::ConstantEnv.new(
452
+ factory: checker.factory,
453
+ context: new_nesting,
454
+ resolver: self.module_context.const_env.resolver
455
+ )
465
456
 
466
457
  implement_module_name = implement_module(module_name: new_class_name, super_name: super_class_name, annotations: annots)
467
- module_context = default_module_context(implement_module_name, const_env: class_const_env, current_namespace: new_namespace)
458
+ module_context = default_module_context(implement_module_name, const_env: class_const_env)
468
459
 
469
460
  if implement_module_name
470
461
  if super_class_name && implement_module_name.name == absolute_name(super_class_name)
@@ -534,8 +525,8 @@ module Steep
534
525
  )
535
526
  end
536
527
 
537
- def with_class_constr(node)
538
- constr = for_class(node)
528
+ def with_class_constr(node, new_class_name, super_class_name)
529
+ constr = for_class(node, new_class_name, super_class_name)
539
530
 
540
531
  constr.checker.push_variable_bounds(constr.variable_context.upper_bounds) do
541
532
  yield constr
@@ -553,7 +544,7 @@ module Steep
553
544
  end
554
545
 
555
546
  def for_sclass(node, type)
556
- annots = source.annotations(block: node, factory: checker.factory, current_module: current_namespace)
547
+ annots = source.annotations(block: node, factory: checker.factory, context: nesting)
557
548
 
558
549
  instance_type = if type.is_a?(AST::Types::Self)
559
550
  context.self_type
@@ -601,7 +592,6 @@ module Steep
601
592
  instance_type: annots.instance_type || instance_type,
602
593
  module_type: annots.self_type || annots.module_type || module_type,
603
594
  implement_name: nil,
604
- current_namespace: current_namespace,
605
595
  const_env: self.module_context.const_env,
606
596
  class_name: self.module_context.class_name,
607
597
  module_definition: module_definition,
@@ -642,7 +632,7 @@ module Steep
642
632
  end
643
633
 
644
634
  def for_branch(node, truthy_vars: Set.new, type_case_override: nil, break_context: context.break_context)
645
- annots = source.annotations(block: node, factory: checker.factory, current_module: current_namespace)
635
+ annots = source.annotations(block: node, factory: checker.factory, context: nesting)
646
636
 
647
637
  lvar_env = context.lvar_env
648
638
 
@@ -1497,33 +1487,37 @@ module Steep
1497
1487
  yield_self do
1498
1488
  constr = self
1499
1489
 
1500
- name, sup, _ = node.children
1501
- if name.type == :const
1502
- # skip the last constant reference
1503
- if const_parent = name.children[0]
1504
- _, constr = constr.synthesize(const_parent)
1490
+ name_node, super_node, _ = node.children
1491
+ _, constr, class_name = synthesize_constant(name_node, name_node.children[0], name_node.children[1]) do
1492
+ typing.add_error(
1493
+ Diagnostic::Ruby::UnknownConstant.new(node: name_node, name: name_node.children[1]).class!
1494
+ )
1495
+ end
1496
+ if class_name
1497
+ typing.source_index.add_definition(constant: class_name, definition: name_node)
1498
+ end
1499
+
1500
+ if super_node
1501
+ _, constr, super_name = constr.synthesize_constant(super_node, super_node.children[0], super_node.children[1]) do
1502
+ typing.add_error(
1503
+ Diagnostic::Ruby::UnknownConstant.new(node: super_node, name: super_node.children[1]).class!
1504
+ )
1505
+ end
1506
+ if super_name
1507
+ typing.source_index.add_reference(constant: super_name, ref: super_node)
1505
1508
  end
1506
- else
1507
- _, constr = constr.synthesize(name)
1508
1509
  end
1509
- _, constr = constr.synthesize(sup) if sup
1510
1510
 
1511
- with_class_constr(node) do |constructor|
1511
+ with_class_constr(node, class_name, super_name) do |constructor|
1512
1512
  if module_type = constructor.module_context&.module_type
1513
1513
  _, constructor = constructor.add_typing(name, type: module_type)
1514
1514
  else
1515
1515
  _, constructor = constructor.fallback_to_any(name)
1516
1516
  end
1517
1517
 
1518
- constructor.typing.source_index.add_definition(
1519
- constant: constructor.module_context.class_name,
1520
- definition: node
1521
- )
1522
-
1523
1518
  constructor.typing.add_context_for_node(node, context: constructor.context)
1524
1519
  constructor.typing.add_context_for_body(node, context: constructor.context)
1525
1520
 
1526
- constructor.synthesize(node.children[1]) if node.children[1]
1527
1521
  constructor.synthesize(node.children[2]) if node.children[2]
1528
1522
 
1529
1523
  if constructor.module_context&.implement_name && !namespace_module?(node)
@@ -1538,28 +1532,22 @@ module Steep
1538
1532
  yield_self do
1539
1533
  constr = self
1540
1534
 
1541
- name, _ = node.children
1542
- if name.type == :const
1543
- # skip the last constant reference
1544
- if const_parent = name.children[0]
1545
- _, constr = constr.synthesize(const_parent)
1546
- end
1547
- else
1548
- _, constr = constr.synthesize(name)
1535
+ name_node, _ = node.children
1536
+ _, constr, module_name = synthesize_constant(name_node, name_node.children[0], name_node.children[1]) do
1537
+ typing.add_error Diagnostic::Ruby::UnknownConstant.new(node: name_node, name: name_node.children[1]).module!
1538
+ end
1539
+
1540
+ if module_name
1541
+ constr.typing.source_index.add_definition(constant: module_name, definition: name_node)
1549
1542
  end
1550
1543
 
1551
- with_module_constr(node) do |constructor|
1544
+ with_module_constr(node, module_name) do |constructor|
1552
1545
  if module_type = constructor.module_context&.module_type
1553
1546
  _, constructor = constructor.add_typing(name, type: module_type)
1554
1547
  else
1555
1548
  _, constructor = constructor.fallback_to_any(name)
1556
1549
  end
1557
1550
 
1558
- constructor.typing.source_index.add_definition(
1559
- constant: constructor.module_context.class_name,
1560
- definition: node
1561
- )
1562
-
1563
1551
  constructor.typing.add_context_for_node(node, context: constructor.context)
1564
1552
  constructor.typing.add_context_for_body(node, context: constructor.context)
1565
1553
 
@@ -1611,75 +1599,47 @@ module Steep
1611
1599
  add_typing node, type: AST::Types::Void.new
1612
1600
 
1613
1601
  when :const
1614
- parent = node.children[0]
1615
- if parent
1616
- _, constr = synthesize(parent)
1617
- else
1618
- constr = self
1619
- end
1620
-
1621
- const_name = constr.module_name_from_node(node)
1602
+ yield_self do
1603
+ type, constr, name = synthesize_constant(node, node.children[0], node.children[1])
1622
1604
 
1623
- if const_name
1624
- if constant = module_context.const_env.lookup_constant(const_name)
1625
- typing.source_index.add_reference(constant: constant.name, ref: node)
1605
+ if name
1606
+ typing.source_index.add_reference(constant: name, ref: node)
1626
1607
  end
1627
1608
 
1628
- type = type_env.get(const: const_name) do
1629
- constr.fallback_to_any(node)
1630
- end
1631
- constr.add_typing(node, type: type)
1632
- else
1633
- constr.fallback_to_any(node)
1609
+ Pair.new(type: type, constr: constr)
1634
1610
  end
1635
1611
 
1636
1612
  when :casgn
1637
1613
  yield_self do
1638
- constr = self
1614
+ constant_type, constr, constant_name = synthesize_constant(nil, node.children[0], node.children[1]) do
1615
+ typing.add_error(
1616
+ Diagnostic::Ruby::UnknownConstant.new(
1617
+ node: node,
1618
+ name: node.children[1]
1619
+ )
1620
+ )
1621
+ end
1639
1622
 
1640
- parent = node.children[0]
1641
- _, constr = constr.synthesize(parent) if parent
1642
- const_name = constr.module_name_from_node(node)
1623
+ if constant_name
1624
+ typing.source_index.add_definition(constant: constant_name, definition: node)
1625
+ end
1643
1626
 
1644
- if const_name
1645
- if constant = module_context.const_env.lookup_constant(const_name)
1646
- typing.source_index.add_definition(constant: constant.name, definition: node)
1647
- end
1627
+ value_type, constr = constr.synthesize(node.children.last, hint: constant_type)
1648
1628
 
1649
- const_type = type_env.get(const: const_name) {}
1650
- value_type, constr = constr.synthesize(node.children.last, hint: const_type)
1651
- type = type_env.assign(
1652
- const: const_name,
1653
- type: value_type,
1654
- self_type: self_type,
1655
- instance_type: module_context.instance_type,
1656
- class_type: module_context.module_type
1657
- ) do |error|
1658
- if error
1659
- const_type = type_env.get(const: const_name)
1660
- typing.add_error(
1661
- Diagnostic::Ruby::IncompatibleAssignment.new(
1662
- node: node,
1663
- lhs_type: const_type,
1664
- rhs_type: value_type,
1665
- result: error
1666
- )
1667
- )
1668
- else
1669
- typing.add_error(
1670
- Diagnostic::Ruby::UnknownConstantAssigned.new(
1671
- node: node,
1672
- name: const_name,
1673
- context: module_context
1674
- )
1675
- )
1676
- end
1677
- end
1629
+ result = check_relation(sub_type: value_type, super_type: constant_type)
1630
+ if result.failure?
1631
+ typing.add_error(
1632
+ Diagnostic::Ruby::IncompatibleAssignment.new(
1633
+ node: node,
1634
+ lhs_type: constant_type,
1635
+ rhs_type: value_type,
1636
+ result: result
1637
+ )
1638
+ )
1678
1639
 
1679
- constr.add_typing(node, type: type)
1640
+ constr.add_typing(node, type: constant_type)
1680
1641
  else
1681
- _, constr = constr.synthesize(node.children.last)
1682
- constr.fallback_to_any(node)
1642
+ constr.add_typing(node, type: value_type)
1683
1643
  end
1684
1644
  end
1685
1645
 
@@ -2275,13 +2235,10 @@ module Steep
2275
2235
  type, constr = synthesize(rhs, hint: hint)
2276
2236
  constr.ivasgn(asgn, type)
2277
2237
  when :send
2278
- rhs_ = node.updated(:send,
2279
- [
2280
- asgn.children[0],
2281
- :"#{asgn.children[1]}=",
2282
- asgn.children[2],
2283
- rhs
2284
- ])
2238
+ children = asgn.children.dup
2239
+ children[1] = :"#{children[1]}="
2240
+ send_arg_nodes = [*children, rhs]
2241
+ rhs_ = node.updated(:send, send_arg_nodes)
2285
2242
  node_type = case node.type
2286
2243
  when :or_asgn
2287
2244
  :or
@@ -2348,11 +2305,11 @@ module Steep
2348
2305
  interface = calculate_interface(param_type, private: true)
2349
2306
  method = interface.methods[value.children[0]]
2350
2307
  if method
2351
- return_types = method.method_types.select {|method_type|
2352
- method_type.type.params.empty?
2353
- }.map {|method_type|
2354
- method_type.type.return_type
2355
- }
2308
+ return_types = method.method_types.filter_map do |method_type|
2309
+ if method_type.type.params.optional?
2310
+ method_type.type.return_type
2311
+ end
2312
+ end
2356
2313
 
2357
2314
  unless return_types.empty?
2358
2315
  type = AST::Types::Proc.new(
@@ -2360,7 +2317,7 @@ module Steep
2360
2317
  params: Interface::Function::Params.empty.with_first_param(
2361
2318
  Interface::Function::Params::PositionalParams::Required.new(param_type)
2362
2319
  ),
2363
- return_type: AST::Types::Union.build(types: return_types),
2320
+ return_type: return_types[0],
2364
2321
  location: nil
2365
2322
  ),
2366
2323
  block: nil
@@ -2727,6 +2684,82 @@ module Steep
2727
2684
  end
2728
2685
  end
2729
2686
 
2687
+ def synthesize_constant(node, parent_node, constant_name)
2688
+ const_name = module_name_from_node(parent_node, constant_name)
2689
+
2690
+ if const_name && type = type_env.get(const: const_name) { break }
2691
+ # const-type annotation wins
2692
+ if node
2693
+ constr = synthesize_children(node)
2694
+ type, constr = constr.add_typing(node, type: type)
2695
+ [type, constr, nil]
2696
+ else
2697
+ [type, self, nil]
2698
+ end
2699
+ else
2700
+ case
2701
+ when !parent_node
2702
+ constr = self
2703
+
2704
+ if (type, name = module_context.const_env.resolve(constant_name))
2705
+ if node
2706
+ _, constr = add_typing(node, type: type)
2707
+ end
2708
+
2709
+ return [type, constr, name]
2710
+ end
2711
+ when parent_node.type == :cbase
2712
+ _, constr = add_typing(parent_node, type: AST::Builtin.nil_type)
2713
+
2714
+ if (type, name = constr.module_context.const_env.toplevel(constant_name))
2715
+ if node
2716
+ _, constr = constr.add_typing(node, type: type)
2717
+ end
2718
+
2719
+ return [type, constr, name]
2720
+ end
2721
+ else
2722
+ parent_type, constr = synthesize(parent_node)
2723
+ parent_type = deep_expand_alias(parent_type)
2724
+
2725
+ case parent_type
2726
+ when AST::Types::Name::Singleton
2727
+ if (type, name = module_context.const_env.resolve_child(parent_type.name, constant_name))
2728
+ if node
2729
+ _, constr = add_typing(node, type: type)
2730
+ end
2731
+
2732
+ return [type, constr, name]
2733
+ end
2734
+ when AST::Types::Any
2735
+ # Couldn't detect the type of the parent constant
2736
+ # Skip reporting error for this node.
2737
+ if node
2738
+ _, constr = add_typing(node, type: parent_type)
2739
+ end
2740
+
2741
+ return [parent_type, constr, nil]
2742
+ end
2743
+ end
2744
+
2745
+ if block_given?
2746
+ yield
2747
+ else
2748
+ if node
2749
+ constr.typing.add_error(
2750
+ Diagnostic::Ruby::UnknownConstant.new(node: node, name: constant_name)
2751
+ )
2752
+ end
2753
+ end
2754
+
2755
+ if node
2756
+ _, constr = add_typing(node, type: AST::Builtin.any_type)
2757
+ end
2758
+
2759
+ [AST::Builtin.any_type, constr, nil]
2760
+ end
2761
+ end
2762
+
2730
2763
  def optional_proc?(type)
2731
2764
  if type.is_a?(AST::Types::Union)
2732
2765
  if type.types.size == 2
@@ -2740,7 +2773,7 @@ module Steep
2740
2773
  end
2741
2774
 
2742
2775
  def type_lambda(node, params_node:, body_node:, type_hint:)
2743
- block_annotations = source.annotations(block: node, factory: checker.factory, current_module: current_namespace)
2776
+ block_annotations = source.annotations(block: node, factory: checker.factory, context: nesting)
2744
2777
  params = TypeInference::BlockParams.from_node(params_node, annotations: block_annotations)
2745
2778
 
2746
2779
  type_hint = deep_expand_alias(type_hint) if type_hint
@@ -2897,7 +2930,7 @@ module Steep
2897
2930
 
2898
2931
  constr = synthesize_children(node, skips: skips)
2899
2932
  if block_params
2900
- block_annotations = source.annotations(block: node, factory: checker.factory, current_module: current_namespace)
2933
+ block_annotations = source.annotations(block: node, factory: checker.factory, context: nesting)
2901
2934
 
2902
2935
  constr.type_block_without_hint(
2903
2936
  node: node,
@@ -2918,7 +2951,7 @@ module Steep
2918
2951
 
2919
2952
  constr = synthesize_children(node, skips: skips)
2920
2953
  if block_params
2921
- block_annotations = source.annotations(block: node, factory: checker.factory, current_module: current_namespace)
2954
+ block_annotations = source.annotations(block: node, factory: checker.factory, context: nesting)
2922
2955
 
2923
2956
  constr.type_block_without_hint(
2924
2957
  node: node,
@@ -3299,7 +3332,7 @@ module Steep
3299
3332
 
3300
3333
  if block_params
3301
3334
  # block is given
3302
- block_annotations = source.annotations(block: node, factory: checker.factory, current_module: current_namespace)
3335
+ block_annotations = source.annotations(block: node, factory: checker.factory, context: nesting)
3303
3336
  block_params_ = TypeInference::BlockParams.from_node(block_params, annotations: block_annotations)
3304
3337
 
3305
3338
  if method_type.block
@@ -3641,8 +3674,7 @@ module Steep
3641
3674
  if implements = block_annotations.implement_module_annotation
3642
3675
  module_context = default_module_context(
3643
3676
  implements.name,
3644
- const_env: self.module_context.const_env,
3645
- current_namespace: current_namespace
3677
+ const_env: self.module_context.const_env
3646
3678
  )
3647
3679
 
3648
3680
  self_type = module_context.module_type
@@ -3696,30 +3728,25 @@ module Steep
3696
3728
  end
3697
3729
  end
3698
3730
 
3699
- def current_namespace
3700
- module_context&.current_namespace || AST::Namespace.root
3731
+ def nesting
3732
+ module_context&.nesting
3701
3733
  end
3702
3734
 
3703
- def nested_namespace_for_module(module_name)
3704
- if module_name.namespace.relative?
3705
- (current_namespace + module_name.namespace).append(module_name.name)
3706
- else
3707
- module_name.to_namespace
3735
+ def absolute_nested_module_name(module_name)
3736
+ n = nesting
3737
+ while n && !n[1]
3738
+ n = n[0]
3708
3739
  end
3709
- end
3710
3740
 
3711
- def absolute_name(module_name)
3712
- if current_namespace
3713
- module_name.with_prefix(current_namespace)
3714
- else
3741
+ if n
3715
3742
  module_name.absolute!
3743
+ else
3744
+ n + module_name
3716
3745
  end
3717
3746
  end
3718
3747
 
3719
- def absolute_type(type)
3720
- if type
3721
- checker.builder.absolute_type(type, current: current_namespace)
3722
- end
3748
+ def absolute_name(name)
3749
+ checker.factory.absolute_type_name(name, context: nesting)
3723
3750
  end
3724
3751
 
3725
3752
  def union_type(*types)
@@ -3948,6 +3975,20 @@ module Steep
3948
3975
  constr.add_typing(node, type: AST::Types::Tuple.new(types: element_types))
3949
3976
  end
3950
3977
 
3978
+ def try_convert(type, method)
3979
+ interface = checker.factory.interface(type, private: false)
3980
+ if entry = interface.methods[method]
3981
+ method_type = entry.method_types.find do |method_type|
3982
+ method_type.type.params.optional?
3983
+ end
3984
+
3985
+ method_type.type.return_type
3986
+ end
3987
+ rescue => exn
3988
+ Steep.log_error(exn, message: "Unexpected error when converting #{type.to_s} with #{method}")
3989
+ nil
3990
+ end
3991
+
3951
3992
  def try_array_type(node, hint)
3952
3993
  element_hint = hint ? hint.args[0] : nil
3953
3994
 
@@ -3958,8 +3999,14 @@ module Steep
3958
3999
  case child.type
3959
4000
  when :splat
3960
4001
  type, constr = constr.synthesize(child.children[0], hint: hint)
3961
- if AST::Builtin::Array.instance_type?(type)
4002
+
4003
+ type = try_convert(type, :to_a) || type
4004
+
4005
+ case
4006
+ when AST::Builtin::Array.instance_type?(type)
3962
4007
  element_types << type.args[0]
4008
+ when type.is_a?(AST::Types::Tuple)
4009
+ element_types.push(*type.types)
3963
4010
  else
3964
4011
  element_types.push(*flatten_array_elements(type))
3965
4012
  end
@@ -2,33 +2,51 @@ module Steep
2
2
  module TypeInference
3
3
  class ConstantEnv
4
4
  attr_reader :context
5
- attr_reader :cache
6
5
  attr_reader :factory
7
- attr_reader :table
6
+ attr_reader :resolver
8
7
 
9
8
  # ConstantEnv receives an TypeName as a context, not a Namespace, because this is a simulation of Ruby.
10
9
  # Any namespace is a module or class.
11
- def initialize(factory:, context:)
10
+ def initialize(factory:, context:, resolver:)
12
11
  @cache = {}
13
12
  @factory = factory
14
13
  @context = context
15
- @table = RBS::ConstantTable.new(builder: factory.definition_builder)
14
+ @resolver = resolver
16
15
  end
17
16
 
18
- def lookup_constant(name)
19
- table.resolve_constant_reference(name, context: context)
17
+ def resolve(name)
18
+ decompose_constant(
19
+ resolver.resolve(name, context: context)
20
+ )
20
21
  end
21
22
 
22
- def lookup(name)
23
- cache[name] ||= begin
24
- constant = lookup_constant(name)
23
+ def toplevel(name)
24
+ decompose_constant(
25
+ resolver.table.toplevel[name]
26
+ )
27
+ end
28
+
29
+ def constants
30
+ resolver.constants(context).transform_values {|c| decompose_constant(c) }
31
+ end
32
+
33
+ def resolve_child(module_name, constant_name)
34
+ decompose_constant(
35
+ resolver.resolve_child(module_name, constant_name)
36
+ )
37
+ end
38
+
39
+ def children(module_name)
40
+ resolver.children(module_name).transform_values {|c| decompose_constant(c) }
41
+ end
25
42
 
26
- if constant
27
- factory.type(constant.type)
28
- end
29
- rescue => exn
30
- Steep.logger.debug "Looking up a constant failed: name=#{name}, context=[#{context.join(", ")}], error=#{exn.inspect}"
31
- nil
43
+ def decompose_constant(constant)
44
+ if constant
45
+ [
46
+ factory.type(constant.type),
47
+ constant.name,
48
+ constant.entry
49
+ ]
32
50
  end
33
51
  end
34
52
  end