yoda-language-server 0.9.0 → 0.10.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/client/vscode/package-lock.json +6 -6
- data/client/vscode/src/check-versions.ts +5 -11
- data/client/vscode/src/install-tools.ts +1 -1
- data/lib/yoda/cli/analyze_deps.rb +46 -25
- data/lib/yoda/id_mask.rb +84 -0
- data/lib/yoda/model/descriptions/require_path_description.rb +45 -0
- data/lib/yoda/model/descriptions.rb +1 -0
- data/lib/yoda/model/node_signatures/node.rb +9 -1
- data/lib/yoda/model/values/literal_value.rb +3 -0
- data/lib/yoda/parsing/location.rb +9 -0
- data/lib/yoda/services/loadable_path_resolver.rb +33 -0
- data/lib/yoda/services.rb +1 -0
- data/lib/yoda/store/actions/read_project_files.rb +9 -7
- data/lib/yoda/store/adapters/gdbm_adapter/namespace_accessor.rb +1 -1
- data/lib/yoda/store/adapters/memory_adapter.rb +1 -1
- data/lib/yoda/store/objects/libraries_status.rb +1 -1
- data/lib/yoda/store/objects/library/core.rb +8 -0
- data/lib/yoda/store/objects/library/gem.rb +14 -3
- data/lib/yoda/store/objects/library/path_resolvable.rb +29 -0
- data/lib/yoda/store/objects/library/std.rb +9 -0
- data/lib/yoda/store/objects/library.rb +1 -0
- data/lib/yoda/store/objects/patch.rb +1 -1
- data/lib/yoda/store/objects/patch_set.rb +2 -2
- data/lib/yoda/store/project/dependency.rb +22 -4
- data/lib/yoda/store/project/file_finder.rb +20 -0
- data/lib/yoda/store/project.rb +2 -0
- data/lib/yoda/store/registry/cache.rb +2 -2
- data/lib/yoda/store/registry/composer.rb +9 -7
- data/lib/yoda/store/registry/index.rb +14 -10
- data/lib/yoda/store/registry/library_registry.rb +1 -1
- data/lib/yoda/store/registry.rb +1 -1
- data/lib/yoda/typing/constant_resolver/code_query.rb +25 -0
- data/lib/yoda/typing/constant_resolver/query.rb +12 -1
- data/lib/yoda/typing/constant_resolver.rb +13 -8
- data/lib/yoda/typing/inferencer/load_resolver.rb +37 -0
- data/lib/yoda/typing/inferencer/tracer.rb +32 -0
- data/lib/yoda/typing/inferencer.rb +3 -2
- data/lib/yoda/typing/node_info.rb +5 -0
- data/lib/yoda/typing/tree/{defined.rb → ask_defined.rb} +3 -2
- data/lib/yoda/typing/tree/base.rb +65 -20
- data/lib/yoda/typing/tree/begin.rb +5 -5
- data/lib/yoda/typing/tree/block_call.rb +26 -0
- data/lib/yoda/typing/tree/case.rb +8 -19
- data/lib/yoda/typing/tree/class_tree.rb +10 -18
- data/lib/yoda/typing/tree/conditional_loop.rb +15 -0
- data/lib/yoda/typing/tree/constant.rb +19 -0
- data/lib/yoda/typing/tree/constant_assignment.rb +2 -2
- data/lib/yoda/typing/tree/ensure.rb +17 -0
- data/lib/yoda/typing/tree/for.rb +7 -0
- data/lib/yoda/typing/tree/hash_tree.rb +32 -0
- data/lib/yoda/typing/tree/if.rb +10 -5
- data/lib/yoda/typing/tree/interpolation_text.rb +21 -0
- data/lib/yoda/typing/tree/literal.rb +8 -36
- data/lib/yoda/typing/tree/literal_inferable.rb +48 -0
- data/lib/yoda/typing/tree/local_exit.rb +15 -0
- data/lib/yoda/typing/tree/logical_assignment.rb +5 -5
- data/lib/yoda/typing/tree/logical_operator.rb +6 -5
- data/lib/yoda/typing/tree/method_def.rb +41 -0
- data/lib/yoda/typing/tree/method_inferable.rb +51 -0
- data/lib/yoda/typing/tree/module_tree.rb +7 -20
- data/lib/yoda/typing/tree/multiple_assignment.rb +6 -10
- data/lib/yoda/typing/tree/namespace_inferable.rb +20 -0
- data/lib/yoda/typing/tree/rescue.rb +18 -0
- data/lib/yoda/typing/tree/rescue_clause.rb +42 -0
- data/lib/yoda/typing/tree/self.rb +2 -1
- data/lib/yoda/typing/tree/send.rb +8 -60
- data/lib/yoda/typing/tree/send_inferable.rb +89 -0
- data/lib/yoda/typing/tree/singleton_class_tree.rb +24 -0
- data/lib/yoda/typing/tree/singleton_method_def.rb +41 -0
- data/lib/yoda/typing/tree/super.rb +9 -2
- data/lib/yoda/typing/tree/variable.rb +5 -10
- data/lib/yoda/typing/tree/variable_assignment.rb +11 -8
- data/lib/yoda/typing/tree/yield.rb +9 -2
- data/lib/yoda/typing/tree.rb +55 -22
- data/lib/yoda/typing.rb +1 -0
- data/lib/yoda/version.rb +1 -1
- data/lib/yoda.rb +1 -0
- metadata +25 -13
- data/lib/yoda/typing/inferencer/ast_traverser.rb +0 -408
- data/lib/yoda/typing/tree/block.rb +0 -12
- data/lib/yoda/typing/tree/const.rb +0 -12
- data/lib/yoda/typing/tree/escape.rb +0 -12
- data/lib/yoda/typing/tree/hash_body.rb +0 -36
- data/lib/yoda/typing/tree/literal_with_interpolation.rb +0 -21
- data/lib/yoda/typing/tree/method.rb +0 -43
- data/lib/yoda/typing/tree/rescue_body.rb +0 -12
- data/lib/yoda/typing/tree/singleton_method.rb +0 -47
- data/lib/yoda/typing/tree/while.rb +0 -12
@@ -2,26 +2,15 @@ module Yoda
|
|
2
2
|
module Typing
|
3
3
|
module Tree
|
4
4
|
class Case < Base
|
5
|
-
#
|
6
|
-
|
7
|
-
# TODO
|
8
|
-
Types::Union.new([*when_body_nodes, else_node].map { |node| infer(node) })
|
9
|
-
end
|
10
|
-
|
11
|
-
def children
|
12
|
-
@children ||= [subject, *when_branches, else_branch]
|
13
|
-
end
|
14
|
-
|
15
|
-
def subject
|
16
|
-
@subject ||= build_child(node.children.first)
|
17
|
-
end
|
18
|
-
|
19
|
-
def when_branches
|
20
|
-
@when_branches ||= node.children.slice(1, -2).map(&method(:build_child))
|
21
|
-
end
|
5
|
+
# @!method node
|
6
|
+
# @return [AST::CaseNode]
|
22
7
|
|
23
|
-
|
24
|
-
|
8
|
+
# @return [Type::Type]
|
9
|
+
def infer_type
|
10
|
+
subject_node, *when_nodes, else_node = node.children
|
11
|
+
infer_child(subject_node)
|
12
|
+
when_body_nodes = when_nodes.map { |node| node.children.last }
|
13
|
+
generator.union_type(*[*when_body_nodes, else_node].compact.map { |node| infer_child(node) })
|
25
14
|
end
|
26
15
|
end
|
27
16
|
end
|
@@ -1,29 +1,21 @@
|
|
1
|
+
require 'yoda/typing/tree/namespace_inferable'
|
2
|
+
|
1
3
|
module Yoda
|
2
4
|
module Typing
|
3
5
|
module Tree
|
4
6
|
class ClassTree < Base
|
5
|
-
|
6
|
-
infer_namespace_node(node)
|
7
|
-
end
|
7
|
+
include NamespaceInferable
|
8
8
|
|
9
|
-
#
|
10
|
-
#
|
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)
|
9
|
+
# @!method node
|
10
|
+
# @return [AST::ClassNode]
|
21
11
|
|
22
|
-
|
23
|
-
|
12
|
+
# @return [Types::Base]
|
13
|
+
def infer_type
|
14
|
+
if super_class_node = node.super_class
|
15
|
+
infer_child(super_class_node)
|
24
16
|
end
|
25
17
|
|
26
|
-
|
18
|
+
infer_namespace
|
27
19
|
end
|
28
20
|
end
|
29
21
|
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
|
@@ -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
|
data/lib/yoda/typing/tree/for.rb
CHANGED
@@ -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
|
data/lib/yoda/typing/tree/if.rb
CHANGED
@@ -2,14 +2,19 @@ module Yoda
|
|
2
2
|
module Typing
|
3
3
|
module Tree
|
4
4
|
class If < Base
|
5
|
-
|
6
|
-
|
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
|
13
|
+
# @param branch_nodes [Array<::AST::Node>]
|
10
14
|
# @return [Types::Base]
|
11
|
-
def infer_branch_nodes(
|
12
|
-
|
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
|
-
|
6
|
-
|
7
|
-
|
7
|
+
include LiteralInferable
|
8
|
+
|
9
|
+
# @!method node
|
10
|
+
# @return [AST::LiteralNode, AST::Node]
|
8
11
|
|
9
|
-
|
10
|
-
|
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
|
-
|
6
|
-
|
7
|
-
end
|
5
|
+
# @!method node
|
6
|
+
# @return [AST::AssignmentNode]
|
8
7
|
|
9
|
-
|
8
|
+
# @return [Types::Type]
|
9
|
+
def infer_type
|
10
10
|
# TODO
|
11
|
-
|
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
|
-
|
6
|
-
|
7
|
-
end
|
5
|
+
# @!method node
|
6
|
+
# @return [AST::LeftOperatorNode, AST::CenterOperatorNode]
|
8
7
|
|
9
|
-
|
10
|
-
|
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
|
-
|
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
|
-
|
23
|
-
|
24
|
-
end
|
9
|
+
# @!method node
|
10
|
+
# @return [AST::ModuleNode]
|
25
11
|
|
26
|
-
|
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
|
-
|
6
|
-
|
7
|
-
end
|
5
|
+
# @!method node
|
6
|
+
# @return [AST::AssignmentNode]
|
8
7
|
|
9
|
-
# @
|
10
|
-
|
11
|
-
|
12
|
-
|
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
|