yoda-language-server 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/.rspec +3 -0
- data/.travis.yml +8 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +78 -0
- data/LICENSE.txt +21 -0
- data/README.md +85 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/client/atom/main.js +27 -0
- data/client/vscode/.gitignore +4 -0
- data/client/vscode/.vscode/launch.json +28 -0
- data/client/vscode/.vscode/settings.json +9 -0
- data/client/vscode/.vscode/tasks.json +20 -0
- data/client/vscode/.vscodeignore +8 -0
- data/client/vscode/CHANGELOG.md +7 -0
- data/client/vscode/README.md +65 -0
- data/client/vscode/package-lock.json +2688 -0
- data/client/vscode/package.json +39 -0
- data/client/vscode/src/extension.ts +42 -0
- data/client/vscode/src/test/extension.test.ts +22 -0
- data/client/vscode/src/test/index.ts +22 -0
- data/client/vscode/tsconfig.json +16 -0
- data/client/vscode/vsc-extension-quickstart.md +33 -0
- data/exe/yoda +27 -0
- data/lib/yoda.rb +11 -0
- data/lib/yoda/evaluation.rb +9 -0
- data/lib/yoda/evaluation/code_completion.rb +65 -0
- data/lib/yoda/evaluation/code_completion/base_provider.rb +57 -0
- data/lib/yoda/evaluation/code_completion/const_provider.rb +90 -0
- data/lib/yoda/evaluation/code_completion/method_provider.rb +82 -0
- data/lib/yoda/evaluation/code_completion/variable_provider.rb +18 -0
- data/lib/yoda/evaluation/comment_completion.rb +70 -0
- data/lib/yoda/evaluation/comment_completion/base_provider.rb +64 -0
- data/lib/yoda/evaluation/comment_completion/param_provider.rb +18 -0
- data/lib/yoda/evaluation/comment_completion/tag_provider.rb +41 -0
- data/lib/yoda/evaluation/comment_completion/type_provider.rb +58 -0
- data/lib/yoda/evaluation/current_node_explain.rb +70 -0
- data/lib/yoda/evaluation/evaluator.rb +103 -0
- data/lib/yoda/evaluation/signature_discovery.rb +83 -0
- data/lib/yoda/model.rb +12 -0
- data/lib/yoda/model/completion_item.rb +56 -0
- data/lib/yoda/model/descriptions.rb +10 -0
- data/lib/yoda/model/descriptions/base.rb +26 -0
- data/lib/yoda/model/descriptions/function_description.rb +40 -0
- data/lib/yoda/model/descriptions/value_description.rb +33 -0
- data/lib/yoda/model/descriptions/word_description.rb +32 -0
- data/lib/yoda/model/function_signatures.rb +13 -0
- data/lib/yoda/model/function_signatures/base.rb +68 -0
- data/lib/yoda/model/function_signatures/constructor.rb +70 -0
- data/lib/yoda/model/function_signatures/formatter.rb +82 -0
- data/lib/yoda/model/function_signatures/method.rb +67 -0
- data/lib/yoda/model/function_signatures/overload.rb +79 -0
- data/lib/yoda/model/function_signatures/parameter_list.rb +108 -0
- data/lib/yoda/model/function_signatures/type_builder.rb +101 -0
- data/lib/yoda/model/node_signature.rb +28 -0
- data/lib/yoda/model/path.rb +96 -0
- data/lib/yoda/model/scoped_path.rb +44 -0
- data/lib/yoda/model/types.rb +84 -0
- data/lib/yoda/model/types/any_type.rb +32 -0
- data/lib/yoda/model/types/base.rb +37 -0
- data/lib/yoda/model/types/duck_type.rb +41 -0
- data/lib/yoda/model/types/function_type.rb +174 -0
- data/lib/yoda/model/types/generic_type.rb +66 -0
- data/lib/yoda/model/types/instance_type.rb +42 -0
- data/lib/yoda/model/types/module_type.rb +42 -0
- data/lib/yoda/model/types/sequence_type.rb +53 -0
- data/lib/yoda/model/types/union_type.rb +56 -0
- data/lib/yoda/model/types/unknown_type.rb +40 -0
- data/lib/yoda/model/types/value_type.rb +58 -0
- data/lib/yoda/model/values.rb +9 -0
- data/lib/yoda/model/values/base.rb +32 -0
- data/lib/yoda/model/values/instance_value.rb +65 -0
- data/lib/yoda/model/values/module_value.rb +72 -0
- data/lib/yoda/parsing.rb +15 -0
- data/lib/yoda/parsing/ast_traversable.rb +18 -0
- data/lib/yoda/parsing/comment_tokenizer.rb +59 -0
- data/lib/yoda/parsing/location.rb +101 -0
- data/lib/yoda/parsing/node_objects.rb +10 -0
- data/lib/yoda/parsing/node_objects/const_node.rb +52 -0
- data/lib/yoda/parsing/node_objects/method_definition.rb +46 -0
- data/lib/yoda/parsing/node_objects/namespace.rb +104 -0
- data/lib/yoda/parsing/node_objects/send_node.rb +72 -0
- data/lib/yoda/parsing/parser.rb +27 -0
- data/lib/yoda/parsing/query.rb +11 -0
- data/lib/yoda/parsing/query/current_comment_query.rb +80 -0
- data/lib/yoda/parsing/query/current_comment_token_query.rb +153 -0
- data/lib/yoda/parsing/query/current_commenting_node_query.rb +68 -0
- data/lib/yoda/parsing/query/current_location_node_query.rb +51 -0
- data/lib/yoda/parsing/query/current_node_comment_query.rb +40 -0
- data/lib/yoda/parsing/range.rb +41 -0
- data/lib/yoda/parsing/scopes.rb +15 -0
- data/lib/yoda/parsing/scopes/base.rb +78 -0
- data/lib/yoda/parsing/scopes/builder.rb +60 -0
- data/lib/yoda/parsing/scopes/class_definition.rb +47 -0
- data/lib/yoda/parsing/scopes/meta_class_definition.rb +44 -0
- data/lib/yoda/parsing/scopes/meta_method_definition.rb +70 -0
- data/lib/yoda/parsing/scopes/method_definition.rb +69 -0
- data/lib/yoda/parsing/scopes/module_definition.rb +36 -0
- data/lib/yoda/parsing/scopes/root.rb +25 -0
- data/lib/yoda/parsing/source_analyzer.rb +59 -0
- data/lib/yoda/parsing/source_cutter.rb +231 -0
- data/lib/yoda/parsing/type_parser.rb +141 -0
- data/lib/yoda/runner.rb +6 -0
- data/lib/yoda/runner/infer.rb +50 -0
- data/lib/yoda/runner/setup.rb +26 -0
- data/lib/yoda/server.rb +191 -0
- data/lib/yoda/server/client_info.rb +98 -0
- data/lib/yoda/server/completion_provider.rb +78 -0
- data/lib/yoda/server/definition_provider.rb +36 -0
- data/lib/yoda/server/deserializer.rb +27 -0
- data/lib/yoda/server/hover_provider.rb +38 -0
- data/lib/yoda/server/signature_provider.rb +46 -0
- data/lib/yoda/store.rb +13 -0
- data/lib/yoda/store/actions.rb +10 -0
- data/lib/yoda/store/actions/import_core_library.rb +30 -0
- data/lib/yoda/store/actions/import_gems.rb +91 -0
- data/lib/yoda/store/actions/read_file.rb +36 -0
- data/lib/yoda/store/actions/read_project_files.rb +29 -0
- data/lib/yoda/store/adapters.rb +14 -0
- data/lib/yoda/store/adapters/base.rb +58 -0
- data/lib/yoda/store/adapters/leveldb_adapter.rb +80 -0
- data/lib/yoda/store/adapters/lmdb_adapter.rb +113 -0
- data/lib/yoda/store/objects.rb +46 -0
- data/lib/yoda/store/objects/addressable.rb +25 -0
- data/lib/yoda/store/objects/base.rb +116 -0
- data/lib/yoda/store/objects/class_object.rb +51 -0
- data/lib/yoda/store/objects/merger.rb +94 -0
- data/lib/yoda/store/objects/meta_class_object.rb +41 -0
- data/lib/yoda/store/objects/method_object.rb +94 -0
- data/lib/yoda/store/objects/module_object.rb +11 -0
- data/lib/yoda/store/objects/namespace_object.rb +67 -0
- data/lib/yoda/store/objects/overload.rb +51 -0
- data/lib/yoda/store/objects/patch.rb +46 -0
- data/lib/yoda/store/objects/patch_set.rb +80 -0
- data/lib/yoda/store/objects/tag.rb +62 -0
- data/lib/yoda/store/objects/value_object.rb +45 -0
- data/lib/yoda/store/project.rb +159 -0
- data/lib/yoda/store/query.rb +12 -0
- data/lib/yoda/store/query/associators.rb +10 -0
- data/lib/yoda/store/query/associators/associate_ancestors.rb +103 -0
- data/lib/yoda/store/query/associators/associate_methods.rb +38 -0
- data/lib/yoda/store/query/base.rb +16 -0
- data/lib/yoda/store/query/find_constant.rb +150 -0
- data/lib/yoda/store/query/find_meta_class.rb +18 -0
- data/lib/yoda/store/query/find_method.rb +74 -0
- data/lib/yoda/store/query/find_signature.rb +43 -0
- data/lib/yoda/store/registry.rb +67 -0
- data/lib/yoda/store/yard_importer.rb +260 -0
- data/lib/yoda/typing.rb +10 -0
- data/lib/yoda/typing/context.rb +96 -0
- data/lib/yoda/typing/environment.rb +35 -0
- data/lib/yoda/typing/evaluator.rb +256 -0
- data/lib/yoda/typing/lexical_scope.rb +26 -0
- data/lib/yoda/typing/relation.rb +15 -0
- data/lib/yoda/typing/traces.rb +9 -0
- data/lib/yoda/typing/traces/base.rb +26 -0
- data/lib/yoda/typing/traces/normal.rb +22 -0
- data/lib/yoda/typing/traces/send.rb +26 -0
- data/lib/yoda/version.rb +3 -0
- data/lib/yoda/yard_extensions.rb +11 -0
- data/lib/yoda/yard_extensions/sig_directive.rb +40 -0
- data/lib/yoda/yard_extensions/type_tag.rb +10 -0
- data/package.json +76 -0
- data/scripts/benchmark.rb +6 -0
- data/scripts/build_core_index.sh +16 -0
- data/yarn.lock +13 -0
- data/yoda-language-server.gemspec +40 -0
- metadata +424 -0
@@ -0,0 +1,82 @@
|
|
1
|
+
module Yoda
|
2
|
+
module Model
|
3
|
+
module FunctionSignatures
|
4
|
+
class Formatter
|
5
|
+
# @return [FunctionSignatures::Base]
|
6
|
+
attr_reader :signature
|
7
|
+
|
8
|
+
# @param signature [FunctionSignatures::Base]
|
9
|
+
def initialize(signature)
|
10
|
+
@signature = signature
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_s
|
14
|
+
"#{signature.name}#{function_signature}"
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def function_signature
|
20
|
+
params = all_parameters
|
21
|
+
(params.empty? ? ': ' : "(#{params.join(', ')}): ") + "#{signature.type.return_type}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def all_parameters
|
25
|
+
[
|
26
|
+
required_parameters,
|
27
|
+
optional_parameters,
|
28
|
+
rest_parameter,
|
29
|
+
post_parameters,
|
30
|
+
required_keyword_parameters,
|
31
|
+
optional_keyword_parameters,
|
32
|
+
keyword_rest_parameter,
|
33
|
+
block_parameter
|
34
|
+
].flatten.compact
|
35
|
+
end
|
36
|
+
|
37
|
+
def required_parameters
|
38
|
+
signature.parameters.required_parameters.map { |param| triple_to_s(param, type_of(param)) }
|
39
|
+
end
|
40
|
+
|
41
|
+
def optional_parameters
|
42
|
+
signature.parameters.optional_parameters.map { |(param, value)| triple_to_s(param, type_of(param), value) }
|
43
|
+
end
|
44
|
+
|
45
|
+
def post_parameters
|
46
|
+
signature.parameters.post_parameters.map { |param| triple_to_s(param, type_of(param)) }
|
47
|
+
end
|
48
|
+
|
49
|
+
def required_keyword_parameters
|
50
|
+
signature.parameters.required_keyword_parameters.map { |param| "#{type_of(param)} #{param}:" }
|
51
|
+
end
|
52
|
+
|
53
|
+
def optional_keyword_parameters
|
54
|
+
signature.parameters.required_keyword_parameters.map { |(param, value)| "#{type_of(param)} #{param}: #{value}" }
|
55
|
+
end
|
56
|
+
|
57
|
+
def rest_parameter
|
58
|
+
signature.parameters.rest_parameter ? "#{type_of(signature.parameters.rest_parameter)} *#{signature.parameters.rest_parameter}" : nil
|
59
|
+
end
|
60
|
+
|
61
|
+
def keyword_rest_parameter
|
62
|
+
signature.parameters.keyword_rest_parameter ? "#{type_of(signature.parameters.keyword_rest_parameter)} **#{signature.parameters.keyword_rest_parameter}" : nil
|
63
|
+
end
|
64
|
+
|
65
|
+
def block_parameter
|
66
|
+
signature.parameters.block_parameter ? "#{type_of(signature.parameters.block_parameter)} **#{signature.parameters.block_parameter}" : nil
|
67
|
+
end
|
68
|
+
|
69
|
+
# @param name [String]
|
70
|
+
# @param type [Base]
|
71
|
+
# @param default_value [String, nil]
|
72
|
+
def triple_to_s(name, type, default_value = nil)
|
73
|
+
"#{type} #{name}" + (default_value ? " = #{ default_value }" : '')
|
74
|
+
end
|
75
|
+
|
76
|
+
def type_of(param)
|
77
|
+
signature.parameter_type_of(param)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Yoda
|
2
|
+
module Model
|
3
|
+
module FunctionSignatures
|
4
|
+
class Method < Base
|
5
|
+
# @type Store::Objects::MethodObject
|
6
|
+
attr_reader :method_object
|
7
|
+
|
8
|
+
# @param method_object [Store::Objects::MethodObject]
|
9
|
+
def initialize(method_object)
|
10
|
+
fail ArgumentError, method_object unless method_object.is_a?(Store::Objects::MethodObject)
|
11
|
+
@method_object = method_object
|
12
|
+
end
|
13
|
+
|
14
|
+
# @return [String]
|
15
|
+
def name
|
16
|
+
method_object.name.to_s
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [String]
|
20
|
+
def sep
|
21
|
+
method_object.sep
|
22
|
+
end
|
23
|
+
|
24
|
+
# @return [String]
|
25
|
+
def namespace_path
|
26
|
+
method_object.namespace_path
|
27
|
+
end
|
28
|
+
|
29
|
+
# @return [String]
|
30
|
+
def document
|
31
|
+
@method_object.document
|
32
|
+
end
|
33
|
+
|
34
|
+
# @return [Types::FunctionType]
|
35
|
+
def type
|
36
|
+
type_builder.type
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return [Array<(String, Integer, Integer)>]
|
40
|
+
def sources
|
41
|
+
method_object.source
|
42
|
+
end
|
43
|
+
|
44
|
+
# @return [(String, Integer, Integer), nil]
|
45
|
+
def primary_source
|
46
|
+
method_object.primary_source
|
47
|
+
end
|
48
|
+
|
49
|
+
# @return [ParameterList]
|
50
|
+
def parameters
|
51
|
+
@parameters ||= ParameterList.new(method_object.parameters)
|
52
|
+
end
|
53
|
+
|
54
|
+
def parameter_type_of(param)
|
55
|
+
type_builder.type_of(param)
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
# @return [TypeBuilder]
|
61
|
+
def type_builder
|
62
|
+
@type_builder ||= TypeBuilder.new(parameters, method_object.tag_list)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module Yoda
|
2
|
+
module Model
|
3
|
+
module FunctionSignatures
|
4
|
+
class Overload < Base
|
5
|
+
# @return [Store::Objects::MethodObject]
|
6
|
+
attr_reader :method_object
|
7
|
+
|
8
|
+
# @return [Store::Objects::Overload]
|
9
|
+
attr_reader :overload
|
10
|
+
|
11
|
+
# @param method_object [Store::Objects::MethodObject]
|
12
|
+
# @param overload [Store::Objects::Overload]
|
13
|
+
def initialize(method_object, overload)
|
14
|
+
fail ArgumentError, method_object unless method_object.is_a?(Store::Objects::MethodObject)
|
15
|
+
fail ArgumentError, overload unless overload.is_a?(Store::Objects::Overload)
|
16
|
+
@method_object = method_object
|
17
|
+
@overload = overload
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [Symbol]
|
21
|
+
def visibility
|
22
|
+
method_object.visibility
|
23
|
+
end
|
24
|
+
|
25
|
+
# @return [String]
|
26
|
+
def name
|
27
|
+
method_object.name
|
28
|
+
end
|
29
|
+
|
30
|
+
# @return [String]
|
31
|
+
def sep
|
32
|
+
method_object.sep
|
33
|
+
end
|
34
|
+
|
35
|
+
# @return [String]
|
36
|
+
def document
|
37
|
+
overload.document || method_object.document
|
38
|
+
end
|
39
|
+
|
40
|
+
# @return [Types::FunctionType]
|
41
|
+
def type
|
42
|
+
@type = type_builder.type
|
43
|
+
end
|
44
|
+
|
45
|
+
# @return [Array<(String, Integer, Integer)>]
|
46
|
+
def sources
|
47
|
+
method_object.sources
|
48
|
+
end
|
49
|
+
|
50
|
+
# @abstract
|
51
|
+
# @return [String]
|
52
|
+
def namespace_path
|
53
|
+
method_object.namespace_path
|
54
|
+
end
|
55
|
+
|
56
|
+
# @return [(String, Integer, Integer), nil]
|
57
|
+
def primary_source
|
58
|
+
overload.primary_source || method_object.primary_source
|
59
|
+
end
|
60
|
+
|
61
|
+
# @return [ParameterList]
|
62
|
+
def parameters
|
63
|
+
@parameters ||= ParameterList.new(overload.parameters)
|
64
|
+
end
|
65
|
+
|
66
|
+
def parameter_type_of(param)
|
67
|
+
type_builder.type_of(param)
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
# @return [TypeBuilder]
|
73
|
+
def type_builder
|
74
|
+
@type_builder ||= TypeBuilder.new(parameters, overload.tag_list)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module Yoda
|
2
|
+
module Model
|
3
|
+
module FunctionSignatures
|
4
|
+
class ParameterList
|
5
|
+
# @return [Array<(String, String)>]
|
6
|
+
attr_reader :parameters
|
7
|
+
|
8
|
+
# @param parameters [Array<(String, String)>]
|
9
|
+
def initialize(parameters)
|
10
|
+
fail ArgumentError, parameters unless parameters.all? { |param| param.is_a?(Array) }
|
11
|
+
@parameters = parameters
|
12
|
+
end
|
13
|
+
|
14
|
+
# @return [Array<(String, String)>]
|
15
|
+
def to_a
|
16
|
+
parameters
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [Enumerator<(String, String)>]
|
20
|
+
def each(*args, &proc)
|
21
|
+
to_a.each(*args, &proc)
|
22
|
+
end
|
23
|
+
|
24
|
+
# @return [Array<String>]
|
25
|
+
def parameter_names
|
26
|
+
parameters.map(&:first)
|
27
|
+
end
|
28
|
+
|
29
|
+
# @return [Array<String>]
|
30
|
+
def required_parameters
|
31
|
+
parameter_options[:required_parameters]
|
32
|
+
end
|
33
|
+
|
34
|
+
# @return [Array<String>]
|
35
|
+
def post_parameters
|
36
|
+
parameter_options[:post_parameters]
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return [Array<(String, String)>]
|
40
|
+
def optional_parameters
|
41
|
+
parameter_options[:optional_parameters]
|
42
|
+
end
|
43
|
+
|
44
|
+
# @return [Array<String>]
|
45
|
+
def required_keyword_parameters
|
46
|
+
parameter_options[:required_keyword_parameters]
|
47
|
+
end
|
48
|
+
|
49
|
+
# @return [Array<(String, String)>]
|
50
|
+
def optional_keyword_parameters
|
51
|
+
parameter_options[:optional_keyword_parameters]
|
52
|
+
end
|
53
|
+
|
54
|
+
# @return [String, nil]
|
55
|
+
def rest_parameter
|
56
|
+
parameter_options[:rest_parameter]
|
57
|
+
end
|
58
|
+
|
59
|
+
# @return [String, nil]
|
60
|
+
def keyword_rest_parameter
|
61
|
+
parameter_options[:keyword_rest_parameter]
|
62
|
+
end
|
63
|
+
|
64
|
+
# @return [String, nil]
|
65
|
+
def block_parameter
|
66
|
+
parameter_options[:block_parameter]
|
67
|
+
end
|
68
|
+
|
69
|
+
# @return [Hash{ Symbol => Object }]
|
70
|
+
def parameter_options
|
71
|
+
@parameter_options ||= begin
|
72
|
+
options = {
|
73
|
+
required_parameters: [],
|
74
|
+
optional_parameters: [],
|
75
|
+
rest_parameter: nil,
|
76
|
+
post_parameters: [],
|
77
|
+
required_keyword_parameters: [],
|
78
|
+
optional_keyword_parameters: [],
|
79
|
+
keyword_rest_parameter: nil,
|
80
|
+
block_parameter: nil,
|
81
|
+
}
|
82
|
+
parameters.each_with_object(options) do |(name, default), obj|
|
83
|
+
if name.to_s.start_with?('**')
|
84
|
+
obj[:keyword_rest_parameter] ||= name.to_s.gsub(/\A\*\*/, '')
|
85
|
+
elsif name.to_s.start_with?('*')
|
86
|
+
obj[:rest_parameter] ||= name.to_s.gsub(/\A\*/, '')
|
87
|
+
elsif name.to_s.start_with?('&')
|
88
|
+
obj[:block_parameter] ||= name.to_s.gsub(/\A\&/, '')
|
89
|
+
elsif name.to_s.end_with?(':')
|
90
|
+
if default && !default.empty?
|
91
|
+
obj[:optional_keyword_parameters].push([name.to_s.gsub(/:\Z/, ''), default])
|
92
|
+
else
|
93
|
+
obj[:required_keyword_parameters].push(name.to_s.gsub(/:\Z/, ''))
|
94
|
+
end
|
95
|
+
elsif default && !default.empty?
|
96
|
+
obj[:optional_parameters].push([name, default])
|
97
|
+
elsif obj[:rest_parameter]
|
98
|
+
obj[:post_parameters].push(name.to_s)
|
99
|
+
else
|
100
|
+
obj[:required_parameters].push(name.to_s)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
module Yoda
|
2
|
+
module Model
|
3
|
+
module FunctionSignatures
|
4
|
+
class TypeBuilder
|
5
|
+
# @return [ParameterList]
|
6
|
+
attr_reader :parameters
|
7
|
+
|
8
|
+
# @return [Array<Store::Objects::Tag>]
|
9
|
+
attr_reader :tag_list
|
10
|
+
|
11
|
+
# @param parameters [ParameterList]
|
12
|
+
# @param tag_list [Array<Store::Objects::Tag>]
|
13
|
+
# @param lexical_scope [Array<Store::Objects::Tag>]
|
14
|
+
def initialize(parameters, tag_list)
|
15
|
+
@parameters = parameters
|
16
|
+
@tag_list = tag_list
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [Types::FunctionType]
|
20
|
+
def type
|
21
|
+
@type ||= begin
|
22
|
+
if !type_tags.empty?
|
23
|
+
parsed_type = parse_type_tag(type_tags.first)
|
24
|
+
parsed_type.is_a?(Types::FunctionType) ? parsed_type : Types::FunctionType.new(return_type: parsed_type)
|
25
|
+
else
|
26
|
+
Types::FunctionType.new(return_type: return_types.first || Types::UnknownType.new('nodoc'), **parameter_options)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# @param param [String]
|
32
|
+
# @return [Types::Base]
|
33
|
+
def type_of(param)
|
34
|
+
param_type_table[param] || Types::UnknownType.new('nodoc')
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
# @param type_tag [Store::Objects::Tag]
|
40
|
+
# @return [Types::FunctionType]
|
41
|
+
def parse_type_tag(tag)
|
42
|
+
parsed_type = Parsing::TypeParser.new.safe_parse(tag.text).change_root(convert_lexical_scope_literals(tag.lexical_scope))
|
43
|
+
parsed_type.is_a?(Types::FunctionType) ? parsed_type : Types::FunctionType.new(return_type: parsed_type)
|
44
|
+
end
|
45
|
+
|
46
|
+
# @return [Hash]
|
47
|
+
def parameter_options
|
48
|
+
@parameter_options ||= {
|
49
|
+
required_parameters: parameters.required_parameters.map(&method(:type_of)),
|
50
|
+
optional_parameters: parameters.optional_parameters.map(&:first).map(&method(:type_of)),
|
51
|
+
rest_parameter: parameters.rest_parameter ? type_of(parameters.rest_parameter) : nil,
|
52
|
+
post_parameters: parameters.post_parameters.map(&method(:type_of)),
|
53
|
+
required_keyword_parameters: parameters.required_keyword_parameters.map(&method(:type_of)),
|
54
|
+
optional_keyword_parameters: parameters.optional_keyword_parameters.map(&:first).map(&method(:type_of)),
|
55
|
+
keyword_rest_parameter: parameters.keyword_rest_parameter ? type_of(parameters.keyword_rest_parameter) : nil,
|
56
|
+
block_parameter: parameters.block_parameter ? type_of(parameters.block_parameter) : nil,
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
# @return [Array<Store::Objects::Tag>]
|
61
|
+
def return_tags
|
62
|
+
@return_tag ||= tag_list.select { |tag| tag.tag_name == 'return' }
|
63
|
+
end
|
64
|
+
|
65
|
+
# @return [Array<Store::Objects::Tag>]
|
66
|
+
def type_tags
|
67
|
+
@type_tag ||= tag_list.select { |tag| tag.tag_name == 'type' }
|
68
|
+
end
|
69
|
+
|
70
|
+
# @return [Array<Store::Objects::Tag>]
|
71
|
+
def param_tags
|
72
|
+
@param_tags ||= tag_list.select { |tag| tag.tag_name == 'param' }
|
73
|
+
end
|
74
|
+
|
75
|
+
# @return [Array<Types::Base>]
|
76
|
+
def return_types
|
77
|
+
@return_types ||= parse_yard_type_tags(return_tags)
|
78
|
+
end
|
79
|
+
|
80
|
+
# @param tags [Array<Store::Objects::Tag>]
|
81
|
+
# @return [Array<Types::Base>]
|
82
|
+
def parse_yard_type_tags(tags)
|
83
|
+
tags.map do |tag|
|
84
|
+
tag.yard_types.empty? ? Types::UnknownType.new('nodoc') : Types.parse_type_strings(tag.yard_types).change_root(convert_lexical_scope_literals(tag.lexical_scope))
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# @return [{ String => Types::Base }]
|
89
|
+
def param_type_table
|
90
|
+
@param_type_table ||= param_tags.map(&:name).zip(parse_yard_type_tags(param_tags)).group_by(&:first).map { |k, v| [k, Types::UnionType.new(v.map(&:last))] }.to_h
|
91
|
+
end
|
92
|
+
|
93
|
+
# @param lexical_scope_literals [Array<String>]
|
94
|
+
# @param [Array<Path>]
|
95
|
+
def convert_lexical_scope_literals(lexical_scope_literals)
|
96
|
+
lexical_scope_literals.map { |literal| Path.new(literal) } + [Path.new('Object')]
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Yoda
|
2
|
+
module Model
|
3
|
+
class NodeSignature
|
4
|
+
attr_reader :node, :trace
|
5
|
+
# @param node [::Parser::AST::Node]
|
6
|
+
# @param trace [Typing::Traces::Base]
|
7
|
+
def initialize(node, trace)
|
8
|
+
@node = node
|
9
|
+
@trace = trace
|
10
|
+
end
|
11
|
+
|
12
|
+
# @return [Range]
|
13
|
+
def node_range
|
14
|
+
Parsing::Range.of_ast_location(node.location)
|
15
|
+
end
|
16
|
+
|
17
|
+
# @return [Array<Descriptions::Base>]
|
18
|
+
def descriptions
|
19
|
+
case trace
|
20
|
+
when Typing::Traces::Send
|
21
|
+
trace.functions.map { |function| Descriptions::FunctionDescription.new(function) }.take(1)
|
22
|
+
else
|
23
|
+
trace.values.map { |value| Descriptions::ValueDescription.new(value) }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|