yoda-language-server 0.8.0 → 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +18 -0
  3. data/README.md +22 -27
  4. data/client/vscode/README.md +17 -2
  5. data/client/vscode/package-lock.json +908 -817
  6. data/client/vscode/package.json +17 -7
  7. data/client/vscode/src/check-versions.ts +49 -0
  8. data/client/vscode/src/config.ts +8 -1
  9. data/client/vscode/src/extension.ts +4 -3
  10. data/client/vscode/src/install-tools.ts +56 -16
  11. data/client/vscode/src/language-server.ts +5 -0
  12. data/client/vscode/src/test/runTest.ts +1 -1
  13. data/client/vscode/src/test/suite/hover.test.ts +13 -25
  14. data/client/vscode/src/test/suite/index.ts +1 -2
  15. data/client/vscode/src/utils.ts +11 -0
  16. data/images/hover-method.png +0 -0
  17. data/images/method-complete.png +0 -0
  18. data/lib/yoda/cli/analyze_deps.rb +46 -25
  19. data/lib/yoda/id_mask.rb +84 -0
  20. data/lib/yoda/instrument.rb +7 -0
  21. data/lib/yoda/model/descriptions/require_path_description.rb +45 -0
  22. data/lib/yoda/model/descriptions.rb +1 -0
  23. data/lib/yoda/model/node_signatures/node.rb +9 -1
  24. data/lib/yoda/model/values/literal_value.rb +3 -0
  25. data/lib/yoda/parsing/location.rb +9 -0
  26. data/lib/yoda/server/concurrent_writer.rb +1 -1
  27. data/lib/yoda/server/lifecycle_handler.rb +101 -78
  28. data/lib/yoda/server/notifier.rb +2 -55
  29. data/lib/yoda/services/loadable_path_resolver.rb +40 -0
  30. data/lib/yoda/services.rb +1 -0
  31. data/lib/yoda/store/actions/read_project_files.rb +9 -7
  32. data/lib/yoda/store/adapters/gdbm_adapter/namespace_accessor.rb +1 -1
  33. data/lib/yoda/store/adapters/memory_adapter.rb +1 -1
  34. data/lib/yoda/store/objects/libraries_status.rb +1 -1
  35. data/lib/yoda/store/objects/library/core.rb +8 -0
  36. data/lib/yoda/store/objects/library/gem.rb +14 -3
  37. data/lib/yoda/store/objects/library/path_resolvable.rb +29 -0
  38. data/lib/yoda/store/objects/library/std.rb +9 -0
  39. data/lib/yoda/store/objects/library.rb +1 -0
  40. data/lib/yoda/store/objects/patch.rb +1 -1
  41. data/lib/yoda/store/objects/patch_set.rb +2 -2
  42. data/lib/yoda/store/project/dependency.rb +22 -4
  43. data/lib/yoda/store/project/file_finder.rb +20 -0
  44. data/lib/yoda/store/project.rb +2 -0
  45. data/lib/yoda/store/registry/cache.rb +2 -2
  46. data/lib/yoda/store/registry/composer.rb +9 -7
  47. data/lib/yoda/store/registry/index.rb +14 -10
  48. data/lib/yoda/store/registry/library_registry.rb +3 -1
  49. data/lib/yoda/store/registry.rb +1 -1
  50. data/lib/yoda/typing/constant_resolver/code_query.rb +25 -0
  51. data/lib/yoda/typing/constant_resolver/query.rb +12 -1
  52. data/lib/yoda/typing/constant_resolver.rb +13 -8
  53. data/lib/yoda/typing/inferencer/load_resolver.rb +37 -0
  54. data/lib/yoda/typing/inferencer/tracer.rb +32 -0
  55. data/lib/yoda/typing/inferencer.rb +3 -2
  56. data/lib/yoda/typing/node_info.rb +5 -0
  57. data/lib/yoda/typing/tree/{defined.rb → ask_defined.rb} +3 -2
  58. data/lib/yoda/typing/tree/base.rb +65 -20
  59. data/lib/yoda/typing/tree/begin.rb +5 -5
  60. data/lib/yoda/typing/tree/block_call.rb +26 -0
  61. data/lib/yoda/typing/tree/case.rb +8 -19
  62. data/lib/yoda/typing/tree/class_tree.rb +10 -18
  63. data/lib/yoda/typing/tree/conditional_loop.rb +15 -0
  64. data/lib/yoda/typing/tree/constant.rb +19 -0
  65. data/lib/yoda/typing/tree/constant_assignment.rb +2 -2
  66. data/lib/yoda/typing/tree/ensure.rb +17 -0
  67. data/lib/yoda/typing/tree/for.rb +7 -0
  68. data/lib/yoda/typing/tree/hash_tree.rb +32 -0
  69. data/lib/yoda/typing/tree/if.rb +10 -5
  70. data/lib/yoda/typing/tree/interpolation_text.rb +21 -0
  71. data/lib/yoda/typing/tree/literal.rb +8 -36
  72. data/lib/yoda/typing/tree/literal_inferable.rb +48 -0
  73. data/lib/yoda/typing/tree/local_exit.rb +15 -0
  74. data/lib/yoda/typing/tree/logical_assignment.rb +5 -5
  75. data/lib/yoda/typing/tree/logical_operator.rb +6 -5
  76. data/lib/yoda/typing/tree/method_def.rb +41 -0
  77. data/lib/yoda/typing/tree/method_inferable.rb +51 -0
  78. data/lib/yoda/typing/tree/module_tree.rb +7 -20
  79. data/lib/yoda/typing/tree/multiple_assignment.rb +6 -10
  80. data/lib/yoda/typing/tree/namespace_inferable.rb +20 -0
  81. data/lib/yoda/typing/tree/rescue.rb +18 -0
  82. data/lib/yoda/typing/tree/rescue_clause.rb +42 -0
  83. data/lib/yoda/typing/tree/self.rb +2 -1
  84. data/lib/yoda/typing/tree/send.rb +8 -60
  85. data/lib/yoda/typing/tree/send_inferable.rb +89 -0
  86. data/lib/yoda/typing/tree/singleton_class_tree.rb +24 -0
  87. data/lib/yoda/typing/tree/singleton_method_def.rb +41 -0
  88. data/lib/yoda/typing/tree/super.rb +9 -2
  89. data/lib/yoda/typing/tree/variable.rb +5 -10
  90. data/lib/yoda/typing/tree/variable_assignment.rb +11 -8
  91. data/lib/yoda/typing/tree/yield.rb +9 -2
  92. data/lib/yoda/typing/tree.rb +55 -22
  93. data/lib/yoda/typing.rb +1 -0
  94. data/lib/yoda/version.rb +1 -1
  95. data/lib/yoda.rb +1 -0
  96. data/yoda-language-server.gemspec +1 -1
  97. metadata +35 -18
  98. data/lib/yoda/typing/inferencer/ast_traverser.rb +0 -408
  99. data/lib/yoda/typing/tree/block.rb +0 -12
  100. data/lib/yoda/typing/tree/const.rb +0 -12
  101. data/lib/yoda/typing/tree/escape.rb +0 -12
  102. data/lib/yoda/typing/tree/hash_body.rb +0 -36
  103. data/lib/yoda/typing/tree/literal_with_interpolation.rb +0 -21
  104. data/lib/yoda/typing/tree/method.rb +0 -43
  105. data/lib/yoda/typing/tree/rescue_body.rb +0 -12
  106. data/lib/yoda/typing/tree/singleton_method.rb +0 -47
  107. data/lib/yoda/typing/tree/while.rb +0 -12
@@ -0,0 +1,15 @@
1
+ module Yoda
2
+ module Typing
3
+ module Tree
4
+ class ConditionalLoop < Base
5
+ # @!method node
6
+ # @return [AST::ConditionalLoopNode]
7
+
8
+ def infer_type
9
+ # TODO
10
+ infer_child(node.body)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,19 @@
1
+ module Yoda
2
+ module Typing
3
+ module Tree
4
+ class Constant < Base
5
+ # @!method node
6
+ # @return [AST::ConstantNode]
7
+
8
+ def infer_type
9
+ query = context.constant_resolver.build_query_for_node(node, tracer: tracer)
10
+ if (base_query = query.base).is_a?(ConstantResolver::CodeQuery)
11
+ base_query.result_type = infer_child(base_query.node)
12
+ end
13
+
14
+ context.constant_resolver.resolve(query)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -2,9 +2,9 @@ module Yoda
2
2
  module Typing
3
3
  module Tree
4
4
  class ConstantAssignment < Base
5
- def process
5
+ def infer_type
6
6
  # TODO
7
- infer(node.children.last)
7
+ infer_child(node.content)
8
8
  end
9
9
  end
10
10
  end
@@ -0,0 +1,17 @@
1
+ module Yoda
2
+ module Typing
3
+ module Tree
4
+ class Ensure < Base
5
+ # @!method node
6
+ # @return [AST::EnsureNode]
7
+
8
+ # @return [Types::Type]
9
+ def infer_type
10
+ type = infer_child(node.body)
11
+ infer_child(node.ensure_body)
12
+ type
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -2,6 +2,13 @@ module Yoda
2
2
  module Typing
3
3
  module Tree
4
4
  class For < Base
5
+ # @!method node
6
+ # @return [AST::ForNode]
7
+
8
+ def infer_type
9
+ # TODO
10
+ infer_child(node.body)
11
+ end
5
12
  end
6
13
  end
7
14
  end
@@ -0,0 +1,32 @@
1
+ module Yoda
2
+ module Typing
3
+ module Tree
4
+ class HashTree < Base
5
+ # @!method node
6
+ # @return [AST::HashNode]
7
+
8
+ # @return [Types::Type]
9
+ def infer_type
10
+ hash = node.contents.each_with_object({}) do |node, memo|
11
+ case node.type
12
+ when :pair
13
+ case node.key.type
14
+ when :sym
15
+ memo[node.key.value.to_sym] = infer_child(node.value)
16
+ when :str
17
+ memo[node.key.value.to_s] = infer_child(node.value)
18
+ else
19
+ # TODO: Support other key types.
20
+ end
21
+ when :kwsplat
22
+ infer_child(node.content)
23
+ # TODO: merge infered result
24
+ end
25
+ end
26
+
27
+ generator.record_type(hash)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -2,14 +2,19 @@ module Yoda
2
2
  module Typing
3
3
  module Tree
4
4
  class If < Base
5
- def type
6
- infer_branch_nodes(node.children.slice(1..2).compact)
5
+ # @!method node
6
+ # @return [AST::IfNode]
7
+
8
+ # @return [Types::Type]
9
+ def infer_type
10
+ infer_branch_nodes(node.children.first, node.children.slice(1..2).compact)
7
11
  end
8
12
 
9
- # @param node [Array<::AST::Node>]
13
+ # @param branch_nodes [Array<::AST::Node>]
10
14
  # @return [Types::Base]
11
- def infer_branch_nodes(nodes)
12
- Types::Union.new(nodes.map { |node| infer(node) })
15
+ def infer_branch_nodes(condition_node, branch_nodes)
16
+ infer_child(condition_node)
17
+ generator.union_type(*branch_nodes.map { |node| infer_child(node) })
13
18
  end
14
19
  end
15
20
  end
@@ -0,0 +1,21 @@
1
+ require 'yoda/typing/tree/literal_inferable'
2
+
3
+ module Yoda
4
+ module Typing
5
+ module Tree
6
+ class InterpolationText < Base
7
+ include LiteralInferable
8
+
9
+ # @!method node
10
+ # @return [AST::InterpolationTextNode]
11
+
12
+ # @return [Types::Type]
13
+ def infer_type
14
+ node.children.each { |node| infer_child(node) }
15
+
16
+ infer_literal(node)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,44 +1,16 @@
1
+ require 'yoda/typing/tree/literal_inferable'
2
+
1
3
  module Yoda
2
4
  module Typing
3
5
  module Tree
4
6
  class Literal < Base
5
- def type
6
- type_for_literal_sexp(node.type)
7
- end
7
+ include LiteralInferable
8
+
9
+ # @!method node
10
+ # @return [AST::LiteralNode, AST::Node]
8
11
 
9
- # @param sexp_type [::Symbol, nil]
10
- # @return [Types::Base]
11
- def type_for_literal_sexp(sexp_type)
12
- case sexp_type
13
- when :dstr, :str, :xstr, :string
14
- generator.string_type
15
- when :dsym, :sym
16
- generator.symbol_type
17
- when :array, :splat
18
- generator.array_type
19
- when :hash
20
- generator.hash_type
21
- when :irange, :erange
22
- generator.range_type
23
- when :regexp
24
- generator.regexp_type
25
- when :true
26
- generator.true_type
27
- when :false
28
- generator.false_type
29
- when :nil
30
- generator.nil_type
31
- when :int
32
- generator.integer_type
33
- when :float
34
- generator.float_type
35
- when :complex
36
- generator.numeric_type
37
- when :rational
38
- generator.numeric_type
39
- else
40
- generator.any_type
41
- end
12
+ def infer_type
13
+ infer_literal(node)
42
14
  end
43
15
  end
44
16
  end
@@ -0,0 +1,48 @@
1
+ module Yoda
2
+ module Typing
3
+ module Tree
4
+ module LiteralInferable
5
+ # @param node [AST::Vnode]
6
+ # @return [Types::Base]
7
+ def infer_literal(node)
8
+ case node.type
9
+ when :dstr, :xstr
10
+ generator.string_type
11
+ when :str, :string
12
+ generator.string_type(node.value.to_s)
13
+ when :dsym
14
+ generator.symbol_type
15
+ when :sym
16
+ generator.symbol_type(node.value.to_sym)
17
+ when :array, :splat
18
+ generator.array_type
19
+ when :hash
20
+ generator.hash_type
21
+ when :irange, :erange
22
+ generator.range_type
23
+ when :regexp
24
+ generator.regexp_type
25
+ when :true
26
+ generator.true_type
27
+ when :false
28
+ generator.false_type
29
+ when :nil
30
+ generator.nil_type
31
+ when :int
32
+ generator.integer_type(node.value.to_i)
33
+ when :float
34
+ generator.float_type
35
+ when :complex
36
+ generator.numeric_type
37
+ when :rational
38
+ generator.numeric_type
39
+ when :empty
40
+ generator.nil_type
41
+ else
42
+ generator.any_type
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,15 @@
1
+ module Yoda
2
+ module Typing
3
+ module Tree
4
+ class LocalExit < Base
5
+ # @!method node
6
+ # @return [AST::SpecialCallNode]
7
+
8
+ def infer_type
9
+ # TODO
10
+ node.arguments[0] ? infer_child(node.arguments[0]) : generator.nil_type
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -2,13 +2,13 @@ module Yoda
2
2
  module Typing
3
3
  module Tree
4
4
  class LogicalAssignment < Base
5
- def children
6
- @children = node.children.map(&method(:build_child))
7
- end
5
+ # @!method node
6
+ # @return [AST::AssignmentNode]
8
7
 
9
- def type
8
+ # @return [Types::Type]
9
+ def infer_type
10
10
  # TODO
11
- infer(node.children.last)
11
+ infer_child(node.content)
12
12
  end
13
13
  end
14
14
  end
@@ -2,12 +2,13 @@ module Yoda
2
2
  module Typing
3
3
  module Tree
4
4
  class LogicalOperator < Base
5
- def children
6
- @children = node.children.map(&method(:build_child))
7
- end
5
+ # @!method node
6
+ # @return [AST::LeftOperatorNode, AST::CenterOperatorNode]
8
7
 
9
- def type
10
- Types::Union.new(node.children.map { |node| infer(node) })
8
+ # @return [Types::Type]
9
+ def infer_type
10
+ # TODO
11
+ generator.union_type(*node.children.map { |node| infer_child(node) })
11
12
  end
12
13
  end
13
14
  end
@@ -0,0 +1,41 @@
1
+ require 'yoda/typing/tree/method_inferable'
2
+
3
+ module Yoda
4
+ module Typing
5
+ module Tree
6
+ class MethodDef < Base
7
+ include MethodInferable
8
+
9
+ # @!method node
10
+ # @return [AST::DefNode]
11
+
12
+ # @return [Types::Base]
13
+ def infer_type
14
+ infer_method_type(receiver_type: self_type)
15
+ end
16
+
17
+ # @return [Symbol]
18
+ def node_name
19
+ node.name
20
+ end
21
+
22
+ # @return [AST::ParametersNode]
23
+ def parameters_node
24
+ node.parameters
25
+ end
26
+
27
+ # @return [Types::Type]
28
+ def body_node
29
+ node.body
30
+ end
31
+
32
+ # @return [Types::Type]
33
+ def self_type
34
+ @self_type ||= begin
35
+ context.method_receiver
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,51 @@
1
+ module Yoda
2
+ module Typing
3
+ module Tree
4
+ module MethodInferable
5
+ # @param receiver_type [Types::Type]
6
+ # @return [Types::Type]
7
+ def infer_method_type(receiver_type:)
8
+ value_resolve_context = generator.value_resolve_context(self_type: receiver_type)
9
+
10
+ method_candidates = receiver_type.value.select_method(node_name.to_s, visibility: %i(private protected public))
11
+ method_types = method_candidates.map(&:rbs_type).map { |type| value_resolve_context.wrap(type) }
12
+
13
+ # TODO: Support overloads
14
+ method_bind = method_types.reduce({}) do |all_bind, method_type|
15
+ bind = Inferencer::ParameterBinder.new(parameters_node.parameter).bind(type: method_type, generator: generator)
16
+ all_bind.merge(bind.to_h) { |_key, v1, v2| generator.union_type(v1, v2) }
17
+ end
18
+
19
+ Logger.trace("method_candidates: [#{method_candidates.join(', ')}]")
20
+ Logger.trace("bind arguments: #{method_bind.map { |key, value| [key, value.to_s] }.to_h }")
21
+
22
+ bind_method_definition(node: node, method_candidates: method_candidates)
23
+
24
+ method_context = context.derive_method_context(receiver_type: receiver_type, binds: method_bind)
25
+
26
+ infer_child(body_node, context: method_context)
27
+
28
+ generator.symbol_type(node_name.to_sym)
29
+ end
30
+
31
+ # @abstract
32
+ # @return [Symbol, string]
33
+ def node_name
34
+ fail NotImplementedError
35
+ end
36
+
37
+ # @abstract
38
+ # @return [AST::ParametersNode]
39
+ def parameters_node
40
+ fail NotImplementedError
41
+ end
42
+
43
+ # @abstract
44
+ # @return [AST::ParametersNode]
45
+ def body_node
46
+ fail NotImplementedError
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -1,29 +1,16 @@
1
+ require 'yoda/typing/tree/namespace_inferable'
2
+
1
3
  module Yoda
2
4
  module Typing
3
5
  module Tree
4
6
  class ModuleTree < Base
5
- def type
6
- infer_namespace_node(node)
7
- end
8
-
9
- # @param node [::AST::Node]
10
- # @return [Types::Base]
11
- def infer_namespace_node(node)
12
- case node.type
13
- when :module
14
- name_node, block_node = node.children
15
- when :class
16
- name_node, _, block_node = node.children
17
- end
18
- constant_resolver = ConstantResolver.new(context: context, node: name_node)
19
- type = constant_resolver.resolve_constant_type
20
- block_context = NamespaceContext.new(objects: [constant_resolver.constant], parent: context, registry: context.registry, receiver: type)
7
+ include NamespaceInferable
21
8
 
22
- if block_node
23
- derive(context: block_context).infer(block_node)
24
- end
9
+ # @!method node
10
+ # @return [AST::ModuleNode]
25
11
 
26
- type
12
+ def infer_type
13
+ infer_namespace
27
14
  end
28
15
  end
29
16
  end
@@ -2,17 +2,13 @@ module Yoda
2
2
  module Typing
3
3
  module Tree
4
4
  class MultipleAssignment < Base
5
- def process
6
- process_bind(node.children[0], node.children[1])
7
- end
5
+ # @!method node
6
+ # @return [AST::AssignmentNode]
8
7
 
9
- # @param var [Symbol]
10
- # @param body_node [::AST::Node]
11
- # @return [Store::Types::Base]
12
- def process_bind(var, body_node)
13
- body_type = infer(body_node)
14
- context.environment.bind(var, body_type)
15
- body_type
8
+ # @return [Types::Type]
9
+ def infer_type
10
+ # TODO
11
+ infer_child(node.content)
16
12
  end
17
13
  end
18
14
  end
@@ -0,0 +1,20 @@
1
+ module Yoda
2
+ module Typing
3
+ module Tree
4
+ module NamespaceInferable
5
+ # @!method node
6
+ # @return [AST::ModuleNode, AST::ClassNode]
7
+
8
+ # @return [Types::Type]
9
+ def infer_namespace
10
+ namespace_type = infer_child(node.receiver)
11
+
12
+ new_context = context.derive_class_context(class_type: namespace_type)
13
+ infer_child(node.body, context: new_context)
14
+
15
+ namespace_type
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,18 @@
1
+ module Yoda
2
+ module Typing
3
+ module Tree
4
+ class Rescue < Base
5
+ # @!method node
6
+ # @return [AST::RescueNode]
7
+
8
+ # @return [Types::Base]
9
+ def infer_type
10
+ type = infer_child(node.body)
11
+ node.rescue_clauses.each { |rescue_clause| infer_child(rescue_clause) }
12
+ infer_child(node.else_clause)
13
+ type
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,42 @@
1
+ module Yoda
2
+ module Typing
3
+ module Tree
4
+ class RescueClause < Base
5
+ # @!method node
6
+ # @return [AST::RescueClauseNode]
7
+
8
+ # @return [Types::Type]
9
+ def infer_type
10
+ binds = {}
11
+
12
+ exception_type = begin
13
+ if node.match_clause
14
+ case node.match_clause.type
15
+ when :array
16
+ generator.union_type(*node.match_clause.contents.map { |content| infer_child(content).instance_type })
17
+ when :empty
18
+ generator.standard_error_type
19
+ else
20
+ # Unexpected
21
+ generator.standard_error_type
22
+ end
23
+ else
24
+ generator.standard_error_type
25
+ end
26
+ end
27
+
28
+
29
+ if node.assignee
30
+ case node.assignee.type
31
+ when :lvasgn
32
+ binds[node.assignee.assignee.name] = exception_type
33
+ end
34
+ end
35
+
36
+ new_context = context.derive_block_context(binds: binds)
37
+ infer_child(node.body, context: new_context)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -2,7 +2,8 @@ module Yoda
2
2
  module Typing
3
3
  module Tree
4
4
  class Self < Base
5
- def type
5
+ # @return [Types::Type]
6
+ def infer_type
6
7
  context.receiver
7
8
  end
8
9
  end
@@ -1,69 +1,17 @@
1
+ require 'yoda/typing/tree/send_inferable'
2
+
1
3
  module Yoda
2
4
  module Typing
3
5
  module Tree
4
6
  class Send < Base
5
- def receiver
6
- @receiver ||= node.children[0] && build_child(node.children[0])
7
- end
8
-
9
- # @return [Symbol]
10
- def method_name
11
- @method_name ||= node.children[1]
12
- end
13
-
14
- # @return [Symbol]
15
- def arguments
16
- @arguments ||= node.children.slice(2..-1).map(&method(:build_child))
17
- end
18
-
19
- # @param block_param_node [::AST::Node, nil]
20
- # @param block_node [::AST::Node, nil]
21
- # @return [Types::Base]
22
- def infer_send_node(block_param_node = nil, block_node = nil)
23
- if block_node
24
- new_context = method_resolver.generate_block_context(context: context, block_param_node: block_param_node)
25
- derive(context: new_context).infer(block_node)
26
- end
27
-
28
- tracer.bind_send(node: node, method_candidates: method_resolver.method_candidates, receiver_candidates: method_resolver.receiver_candidates)
29
- method_resolver.return_type
30
- end
31
-
32
- def method_resolver
33
- @method_resolver ||= MethodResolver.new(
34
- registry: context.registry,
35
- receiver_type: receiver_type,
36
- name: method_name.to_s,
37
- argument_types: argument_types,
38
- generator: generator,
39
- implicit_receiver: receiver.nil?,
40
- )
41
- end
42
-
43
- def receiver_type
44
- @receiver_type ||= receiver ? receiver.type : context.receiver
45
- end
46
-
47
- def block_context
48
- @block_context ||= method_resolver.generate_block_context(context: context, block_param_node: block_param_node)
49
- end
7
+ include SendInferable
50
8
 
51
- private
9
+ # @!method node
10
+ # @return [AST::SendNode]
52
11
 
53
- # @return [{Symbol => Types::Base}]
54
- def argument_types
55
- @argument_types ||= argument_nodes.each_with_object({}) do |node, obj|
56
- case node.type
57
- when :splat
58
- # TODO
59
- node.type
60
- when :blockarg
61
- obj[:block_argument] = infer(node.children.first)
62
- else
63
- obj[:arguments] ||= []
64
- obj[:arguments].push(node.type)
65
- end
66
- end
12
+ # @return [Types::Type]
13
+ def infer_type
14
+ infer_send(node)
67
15
  end
68
16
  end
69
17
  end