yoda-language-server 0.4.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.
Files changed (171) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +8 -0
  5. data/Gemfile +6 -0
  6. data/Gemfile.lock +78 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +85 -0
  9. data/Rakefile +6 -0
  10. data/bin/console +14 -0
  11. data/bin/setup +8 -0
  12. data/client/atom/main.js +27 -0
  13. data/client/vscode/.gitignore +4 -0
  14. data/client/vscode/.vscode/launch.json +28 -0
  15. data/client/vscode/.vscode/settings.json +9 -0
  16. data/client/vscode/.vscode/tasks.json +20 -0
  17. data/client/vscode/.vscodeignore +8 -0
  18. data/client/vscode/CHANGELOG.md +7 -0
  19. data/client/vscode/README.md +65 -0
  20. data/client/vscode/package-lock.json +2688 -0
  21. data/client/vscode/package.json +39 -0
  22. data/client/vscode/src/extension.ts +42 -0
  23. data/client/vscode/src/test/extension.test.ts +22 -0
  24. data/client/vscode/src/test/index.ts +22 -0
  25. data/client/vscode/tsconfig.json +16 -0
  26. data/client/vscode/vsc-extension-quickstart.md +33 -0
  27. data/exe/yoda +27 -0
  28. data/lib/yoda.rb +11 -0
  29. data/lib/yoda/evaluation.rb +9 -0
  30. data/lib/yoda/evaluation/code_completion.rb +65 -0
  31. data/lib/yoda/evaluation/code_completion/base_provider.rb +57 -0
  32. data/lib/yoda/evaluation/code_completion/const_provider.rb +90 -0
  33. data/lib/yoda/evaluation/code_completion/method_provider.rb +82 -0
  34. data/lib/yoda/evaluation/code_completion/variable_provider.rb +18 -0
  35. data/lib/yoda/evaluation/comment_completion.rb +70 -0
  36. data/lib/yoda/evaluation/comment_completion/base_provider.rb +64 -0
  37. data/lib/yoda/evaluation/comment_completion/param_provider.rb +18 -0
  38. data/lib/yoda/evaluation/comment_completion/tag_provider.rb +41 -0
  39. data/lib/yoda/evaluation/comment_completion/type_provider.rb +58 -0
  40. data/lib/yoda/evaluation/current_node_explain.rb +70 -0
  41. data/lib/yoda/evaluation/evaluator.rb +103 -0
  42. data/lib/yoda/evaluation/signature_discovery.rb +83 -0
  43. data/lib/yoda/model.rb +12 -0
  44. data/lib/yoda/model/completion_item.rb +56 -0
  45. data/lib/yoda/model/descriptions.rb +10 -0
  46. data/lib/yoda/model/descriptions/base.rb +26 -0
  47. data/lib/yoda/model/descriptions/function_description.rb +40 -0
  48. data/lib/yoda/model/descriptions/value_description.rb +33 -0
  49. data/lib/yoda/model/descriptions/word_description.rb +32 -0
  50. data/lib/yoda/model/function_signatures.rb +13 -0
  51. data/lib/yoda/model/function_signatures/base.rb +68 -0
  52. data/lib/yoda/model/function_signatures/constructor.rb +70 -0
  53. data/lib/yoda/model/function_signatures/formatter.rb +82 -0
  54. data/lib/yoda/model/function_signatures/method.rb +67 -0
  55. data/lib/yoda/model/function_signatures/overload.rb +79 -0
  56. data/lib/yoda/model/function_signatures/parameter_list.rb +108 -0
  57. data/lib/yoda/model/function_signatures/type_builder.rb +101 -0
  58. data/lib/yoda/model/node_signature.rb +28 -0
  59. data/lib/yoda/model/path.rb +96 -0
  60. data/lib/yoda/model/scoped_path.rb +44 -0
  61. data/lib/yoda/model/types.rb +84 -0
  62. data/lib/yoda/model/types/any_type.rb +32 -0
  63. data/lib/yoda/model/types/base.rb +37 -0
  64. data/lib/yoda/model/types/duck_type.rb +41 -0
  65. data/lib/yoda/model/types/function_type.rb +174 -0
  66. data/lib/yoda/model/types/generic_type.rb +66 -0
  67. data/lib/yoda/model/types/instance_type.rb +42 -0
  68. data/lib/yoda/model/types/module_type.rb +42 -0
  69. data/lib/yoda/model/types/sequence_type.rb +53 -0
  70. data/lib/yoda/model/types/union_type.rb +56 -0
  71. data/lib/yoda/model/types/unknown_type.rb +40 -0
  72. data/lib/yoda/model/types/value_type.rb +58 -0
  73. data/lib/yoda/model/values.rb +9 -0
  74. data/lib/yoda/model/values/base.rb +32 -0
  75. data/lib/yoda/model/values/instance_value.rb +65 -0
  76. data/lib/yoda/model/values/module_value.rb +72 -0
  77. data/lib/yoda/parsing.rb +15 -0
  78. data/lib/yoda/parsing/ast_traversable.rb +18 -0
  79. data/lib/yoda/parsing/comment_tokenizer.rb +59 -0
  80. data/lib/yoda/parsing/location.rb +101 -0
  81. data/lib/yoda/parsing/node_objects.rb +10 -0
  82. data/lib/yoda/parsing/node_objects/const_node.rb +52 -0
  83. data/lib/yoda/parsing/node_objects/method_definition.rb +46 -0
  84. data/lib/yoda/parsing/node_objects/namespace.rb +104 -0
  85. data/lib/yoda/parsing/node_objects/send_node.rb +72 -0
  86. data/lib/yoda/parsing/parser.rb +27 -0
  87. data/lib/yoda/parsing/query.rb +11 -0
  88. data/lib/yoda/parsing/query/current_comment_query.rb +80 -0
  89. data/lib/yoda/parsing/query/current_comment_token_query.rb +153 -0
  90. data/lib/yoda/parsing/query/current_commenting_node_query.rb +68 -0
  91. data/lib/yoda/parsing/query/current_location_node_query.rb +51 -0
  92. data/lib/yoda/parsing/query/current_node_comment_query.rb +40 -0
  93. data/lib/yoda/parsing/range.rb +41 -0
  94. data/lib/yoda/parsing/scopes.rb +15 -0
  95. data/lib/yoda/parsing/scopes/base.rb +78 -0
  96. data/lib/yoda/parsing/scopes/builder.rb +60 -0
  97. data/lib/yoda/parsing/scopes/class_definition.rb +47 -0
  98. data/lib/yoda/parsing/scopes/meta_class_definition.rb +44 -0
  99. data/lib/yoda/parsing/scopes/meta_method_definition.rb +70 -0
  100. data/lib/yoda/parsing/scopes/method_definition.rb +69 -0
  101. data/lib/yoda/parsing/scopes/module_definition.rb +36 -0
  102. data/lib/yoda/parsing/scopes/root.rb +25 -0
  103. data/lib/yoda/parsing/source_analyzer.rb +59 -0
  104. data/lib/yoda/parsing/source_cutter.rb +231 -0
  105. data/lib/yoda/parsing/type_parser.rb +141 -0
  106. data/lib/yoda/runner.rb +6 -0
  107. data/lib/yoda/runner/infer.rb +50 -0
  108. data/lib/yoda/runner/setup.rb +26 -0
  109. data/lib/yoda/server.rb +191 -0
  110. data/lib/yoda/server/client_info.rb +98 -0
  111. data/lib/yoda/server/completion_provider.rb +78 -0
  112. data/lib/yoda/server/definition_provider.rb +36 -0
  113. data/lib/yoda/server/deserializer.rb +27 -0
  114. data/lib/yoda/server/hover_provider.rb +38 -0
  115. data/lib/yoda/server/signature_provider.rb +46 -0
  116. data/lib/yoda/store.rb +13 -0
  117. data/lib/yoda/store/actions.rb +10 -0
  118. data/lib/yoda/store/actions/import_core_library.rb +30 -0
  119. data/lib/yoda/store/actions/import_gems.rb +91 -0
  120. data/lib/yoda/store/actions/read_file.rb +36 -0
  121. data/lib/yoda/store/actions/read_project_files.rb +29 -0
  122. data/lib/yoda/store/adapters.rb +14 -0
  123. data/lib/yoda/store/adapters/base.rb +58 -0
  124. data/lib/yoda/store/adapters/leveldb_adapter.rb +80 -0
  125. data/lib/yoda/store/adapters/lmdb_adapter.rb +113 -0
  126. data/lib/yoda/store/objects.rb +46 -0
  127. data/lib/yoda/store/objects/addressable.rb +25 -0
  128. data/lib/yoda/store/objects/base.rb +116 -0
  129. data/lib/yoda/store/objects/class_object.rb +51 -0
  130. data/lib/yoda/store/objects/merger.rb +94 -0
  131. data/lib/yoda/store/objects/meta_class_object.rb +41 -0
  132. data/lib/yoda/store/objects/method_object.rb +94 -0
  133. data/lib/yoda/store/objects/module_object.rb +11 -0
  134. data/lib/yoda/store/objects/namespace_object.rb +67 -0
  135. data/lib/yoda/store/objects/overload.rb +51 -0
  136. data/lib/yoda/store/objects/patch.rb +46 -0
  137. data/lib/yoda/store/objects/patch_set.rb +80 -0
  138. data/lib/yoda/store/objects/tag.rb +62 -0
  139. data/lib/yoda/store/objects/value_object.rb +45 -0
  140. data/lib/yoda/store/project.rb +159 -0
  141. data/lib/yoda/store/query.rb +12 -0
  142. data/lib/yoda/store/query/associators.rb +10 -0
  143. data/lib/yoda/store/query/associators/associate_ancestors.rb +103 -0
  144. data/lib/yoda/store/query/associators/associate_methods.rb +38 -0
  145. data/lib/yoda/store/query/base.rb +16 -0
  146. data/lib/yoda/store/query/find_constant.rb +150 -0
  147. data/lib/yoda/store/query/find_meta_class.rb +18 -0
  148. data/lib/yoda/store/query/find_method.rb +74 -0
  149. data/lib/yoda/store/query/find_signature.rb +43 -0
  150. data/lib/yoda/store/registry.rb +67 -0
  151. data/lib/yoda/store/yard_importer.rb +260 -0
  152. data/lib/yoda/typing.rb +10 -0
  153. data/lib/yoda/typing/context.rb +96 -0
  154. data/lib/yoda/typing/environment.rb +35 -0
  155. data/lib/yoda/typing/evaluator.rb +256 -0
  156. data/lib/yoda/typing/lexical_scope.rb +26 -0
  157. data/lib/yoda/typing/relation.rb +15 -0
  158. data/lib/yoda/typing/traces.rb +9 -0
  159. data/lib/yoda/typing/traces/base.rb +26 -0
  160. data/lib/yoda/typing/traces/normal.rb +22 -0
  161. data/lib/yoda/typing/traces/send.rb +26 -0
  162. data/lib/yoda/version.rb +3 -0
  163. data/lib/yoda/yard_extensions.rb +11 -0
  164. data/lib/yoda/yard_extensions/sig_directive.rb +40 -0
  165. data/lib/yoda/yard_extensions/type_tag.rb +10 -0
  166. data/package.json +76 -0
  167. data/scripts/benchmark.rb +6 -0
  168. data/scripts/build_core_index.sh +16 -0
  169. data/yarn.lock +13 -0
  170. data/yoda-language-server.gemspec +40 -0
  171. metadata +424 -0
@@ -0,0 +1,96 @@
1
+ module Yoda
2
+ module Model
3
+ class Path
4
+ attr_reader :name
5
+
6
+ # @param path [Path, String]
7
+ # @return [Path]
8
+ def self.build(path)
9
+ path.is_a?(Path) ? path : new(path)
10
+ end
11
+
12
+ # @param names [Array<Path, String>]
13
+ # @return [Path]
14
+ def self.from_names(names)
15
+ new(names.join('::'))
16
+ end
17
+
18
+ # @param name [String]
19
+ def initialize(name)
20
+ fail ArgumentError, name unless name.is_a?(String)
21
+ @name = name
22
+ end
23
+
24
+ def absolute?
25
+ name.start_with?('::')
26
+ end
27
+
28
+ # @return [String]
29
+ def basename
30
+ @basename ||= begin
31
+ if name.end_with?('::')
32
+ ''
33
+ else
34
+ name.split('::').last || ''
35
+ end
36
+ end
37
+ end
38
+
39
+ # @return [String]
40
+ def spacename
41
+ @spacename ||= begin
42
+ if name.end_with?('::')
43
+ name.gsub(/::\Z/, '')
44
+ else
45
+ name.split('::').slice(0..-2).join('::')
46
+ end
47
+ end
48
+ end
49
+
50
+ # @return [String]
51
+ def to_s
52
+ name
53
+ end
54
+
55
+ def split
56
+ name.gsub(/\A::/, '').split('::') + (name.end_with?('::') ? [''] : [])
57
+ end
58
+
59
+ # @param another [Path, String]
60
+ # @return [Path]
61
+ def concat(another)
62
+ if self.class.build(another).absolute?
63
+ self
64
+ else
65
+ self.class.new([self.to_s, another.to_s].reject(&:empty?).join('::'))
66
+ end
67
+ end
68
+
69
+ # @return [Array<String>]
70
+ def namespaces
71
+ name.split('::')
72
+ end
73
+
74
+ # @return [Array<Path>]
75
+ def parent_paths
76
+ if spacename.empty?
77
+ []
78
+ else
79
+ [spacename] + Path.new(spacename).parent_paths
80
+ end
81
+ end
82
+
83
+ def hash
84
+ [self.class.name, name].hash
85
+ end
86
+
87
+ def ==(another)
88
+ eql?(another)
89
+ end
90
+
91
+ def eql?(another)
92
+ another.is_a?(Path) && name == another.name
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,44 @@
1
+ module Yoda
2
+ module Model
3
+ # ScopedPath represents a path name written in namespaces.
4
+ # ScopedPath owns lexical scopes where the path is written.
5
+ class ScopedPath
6
+ # @return [Array<Path>] represents namespaces in order of nearness.
7
+ attr_reader :scopes
8
+
9
+ # @return [Path]
10
+ attr_reader :path
11
+
12
+ # @param path [Path]
13
+ # @return [ScopedPath]
14
+ def self.build(path)
15
+ path.is_a?(ScopedPath) ? path : ScopedPath.new(['Object'], Path.build(path))
16
+ end
17
+
18
+ # @param scopes [Array<Path>] represents namespaces in order of nearness.
19
+ # @param path [Path]
20
+ def initialize(scopes, path)
21
+ @scopes = scopes.map { |pa| Path.build(pa) }
22
+ @path = Path.build(path)
23
+ end
24
+
25
+ # @param paths [Array<String, Path>]
26
+ # @return [ScopedPath]
27
+ def change_scope(paths)
28
+ self.class.new(paths, path)
29
+ end
30
+
31
+ def hash
32
+ [self.class.name, scopes, path].hash
33
+ end
34
+
35
+ def ==(another)
36
+ eql?(another)
37
+ end
38
+
39
+ def eql?(another)
40
+ another.is_a?(ScopedPath) && path == another.path && scopes == another.scopes
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,84 @@
1
+ require 'parslet'
2
+
3
+ module Yoda
4
+ module Model
5
+ module Types
6
+ require 'yoda/model/types/base'
7
+ require 'yoda/model/types/any_type'
8
+ require 'yoda/model/types/value_type'
9
+ require 'yoda/model/types/instance_type'
10
+ require 'yoda/model/types/function_type'
11
+ require 'yoda/model/types/duck_type'
12
+ require 'yoda/model/types/module_type'
13
+ require 'yoda/model/types/sequence_type'
14
+ require 'yoda/model/types/generic_type'
15
+ require 'yoda/model/types/union_type'
16
+ require 'yoda/model/types/unknown_type'
17
+
18
+ # @param string [String]
19
+ # @return [Types::Base]
20
+ def self.parse(string)
21
+ Parsing::Generator.new.apply(Parsing::Parser.new.parse(string))
22
+ rescue Parslet::ParseFailed => failure
23
+ Types::UnknownType.new(string)
24
+ end
25
+
26
+ # @param strings [Array<String>]
27
+ # @return [Types::Base]
28
+ def self.parse_type_strings(strings)
29
+ Types::UnionType.new(strings.map { |string| parse(string) })
30
+ end
31
+
32
+ module Parsing
33
+ class Parser < Parslet::Parser
34
+ rule(:method_name) { match('[a-z]') >> match('[a-zA-Z0-9_]').repeat }
35
+ rule(:duck_type) { str('#') >> method_name.as(:method_name) }
36
+ rule(:constant_name) { match('[A-Z]') >> match('[a-zA-Z0-9_]').repeat }
37
+ rule(:constant_full_name) { str('::').maybe >> (constant_name >> (str('::') | str('.'))).repeat >> constant_name }
38
+ rule(:value_name) { match('[a-z0-9]') >> match('[a-zA-Z0-9_]').repeat }
39
+
40
+ rule(:space) { match('\s').repeat(1) }
41
+ rule(:space?) { space.maybe }
42
+
43
+ rule(:constant_type) { value_name.as(:value) | constant_full_name.as(:instance_type) }
44
+
45
+ rule(:key_value_type) { constant_type.as(:base_type) >> str('{') >> space? >> type.as(:key_type) >> space? >> str('=>') >> space? >> type.as(:value_type) >> space? >> str('}') }
46
+ rule(:sequence_type) { constant_type.as(:base_type) >> str('(') >> space? >> types.as(:value_types) >> space? >> str(')') }
47
+ rule(:generic_type) { constant_type.as(:base_type) >> (str('<') >> space? >> type >> space? >> str('>')).repeat(1).as(:type_arguments) }
48
+
49
+ rule(:shorthand_key_value) { str('{') >> space? >> type.as(:key_type) >> space? >> str('=>') >> space? >> type.as(:value_type) >> space? >> str('}') }
50
+ rule(:shorthand_sequence) { str('(') >> space? >> types.as(:value_types) >> space? >> str(')') }
51
+ rule(:shorthand_array) { str('<') >> space? >> type.as(:type_in_array) >> space? >> str('>') }
52
+
53
+ rule(:union_type) { types.as(:types) }
54
+
55
+ rule(:single_type) { duck_type | shorthand_key_value | shorthand_array | shorthand_sequence | generic_type | key_value_type | sequence_type | constant_type }
56
+ rule(:types) { (single_type >> str(',') >> space?).repeat >> space? >> single_type }
57
+
58
+ rule(:type) { union_type }
59
+ rule(:base) { space? >> type >> space? }
60
+ root :base
61
+ end
62
+
63
+ class Generator < Parslet::Transform
64
+ rule(instance_type: simple(:instance_type)) { Types::InstanceType.new(instance_type.to_s) }
65
+ rule(value: simple(:value)) { Types::ValueType.new(value.to_s) }
66
+
67
+ rule(base_type: simple(:base_type), key_type: simple(:key_type), value_type: simple(:value_type)) { Types::GenericType.from_key_value(base_type, key_type, value_type) }
68
+ rule(base_type: simple(:base_type), value_types: sequence(:value_types)) { Types::SequenceType.new(base_type, value_types) }
69
+ rule(base_type: simple(:base_type), value_types: simple(:value_type)) { Types::SequenceType.new(base_type, [value_type]) }
70
+ rule(base_type: simple(:base_type), type_arguments: sequence(:type_arguments)) { Types::GenericType.new(base_type, type_arguments) }
71
+
72
+ rule(method_name: simple(:method_name)) { Types::DuckType.new(method_name) }
73
+ rule(key_type: simple(:key_type), value_type: simple(:value_type)) { Types::GenericType.from_key_value(Types::InstanceType.new('::Hash'), key_type, value_type) }
74
+ rule(value_types: sequence(:value_types)) { Types::SequenceType.new(Types::InstanceType.new('::Array'), value_types) }
75
+ rule(value_types: simple(:value_type)) { Types::SequenceType.new(Types::InstanceType.new('::Array'), [value_type]) }
76
+ rule(type_in_array: simple(:type)) { Types::GenericType.new(Types::InstanceType.new('::Array'), [type]) }
77
+
78
+ rule(types: sequence(:types)) { Types::UnionType.new(types) }
79
+ rule(types: simple(:type)) { type }
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,32 @@
1
+ module Yoda
2
+ module Model
3
+ module Types
4
+ class AnyType < Base
5
+ def eql?(another)
6
+ another.is_a?(AnyType)
7
+ end
8
+
9
+ def hash
10
+ [self.class.name].hash
11
+ end
12
+
13
+ # @param paths [Array<Paths>]
14
+ # @return [self]
15
+ def change_root(paths)
16
+ self
17
+ end
18
+
19
+ # @param registry [Registry]
20
+ # @return [Array<Store::Objects::Base>]
21
+ def resolve(registry)
22
+ []
23
+ end
24
+
25
+ # @return [String]
26
+ def to_s
27
+ value
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,37 @@
1
+ module Yoda
2
+ module Model
3
+ module Types
4
+ # @abstract
5
+ class Base
6
+ def ==(another)
7
+ eql?(another)
8
+ end
9
+
10
+ # @abstract
11
+ # @param paths [Array<Path>]
12
+ # @return [Base]
13
+ def change_root(paths)
14
+ fail NotImplementedError
15
+ end
16
+
17
+ # @abstract
18
+ # @param registry [Registry]
19
+ # @return [Array<Store::Objects::Base>]
20
+ def resolve(registry)
21
+ fail NotImplementedError
22
+ end
23
+
24
+ # @abstract
25
+ # @return [String]
26
+ def to_s
27
+ fail NotImplementedError
28
+ end
29
+
30
+ # @return [Base]
31
+ def map
32
+ yield self
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,41 @@
1
+ module Yoda
2
+ module Model
3
+ module Types
4
+ class DuckType < Base
5
+ attr_reader :method_name
6
+
7
+ # @param method_name [String]
8
+ def initialize(method_name)
9
+ @method_name = method_name
10
+ end
11
+
12
+ # @param another [Object]
13
+ def eql?(another)
14
+ another.is_a?(DuckType) &&
15
+ method_name == another.method_name
16
+ end
17
+
18
+ def hash
19
+ [self.class.name, method_name].hash
20
+ end
21
+
22
+ # @param paths [Array<Paths>]
23
+ # @return [self]
24
+ def change_root(paths)
25
+ self
26
+ end
27
+
28
+ # @param registry [Registry]
29
+ # @return [Array<Store::Objects::Base>]
30
+ def resolve(registry)
31
+ []
32
+ end
33
+
34
+ # @return [String]
35
+ def to_s
36
+ "##{method_name}"
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,174 @@
1
+ module Yoda
2
+ module Model
3
+ module Types
4
+ class FunctionType < Base
5
+ # @return [Base, nil]
6
+ attr_reader :context
7
+
8
+ # @return [Array<Base>]
9
+ attr_reader :required_parameters, :optional_parameters, :post_parameters
10
+
11
+ # @return [Array<(String, Base)>]
12
+ attr_reader :required_keyword_parameters
13
+
14
+ # @return [Array<(String, Base)>]
15
+ attr_reader :optional_keyword_parameters
16
+
17
+ # @return [Base, nil]
18
+ attr_reader :rest_parameter, :keyword_rest_parameter, :block_parameter
19
+
20
+ # @return [Base]
21
+ attr_reader :return_type
22
+
23
+ # @param context [Base, nil]
24
+ # @param required_parameters [Array<Base>]
25
+ # @param optional_parameters [Array<Base>]
26
+ # @param rest_parameter [Base, nil]
27
+ # @param post_parameters [Array<Base>]
28
+ # @param keyword_parameters [Array<(String, Base)>]
29
+ # @param keyword_rest_parameter [Base, nil]
30
+ # @param block_parameter [Base, nil]
31
+ # @param return_type [Base]
32
+ def initialize(context: nil, return_type:, required_parameters: [], optional_parameters: [], rest_parameter: nil, post_parameters: [], optional_keyword_parameters: [], required_keyword_parameters: [], keyword_rest_parameter: nil, block_parameter: nil)
33
+ @context = context
34
+ @required_parameters = required_parameters
35
+ @optional_parameters = optional_parameters
36
+ @required_keyword_parameters = required_keyword_parameters
37
+ @optional_keyword_parameters = optional_keyword_parameters
38
+ @rest_parameter = rest_parameter
39
+ @post_parameters = post_parameters
40
+ @keyword_rest_parameter = keyword_rest_parameter
41
+ @block_parameter = block_parameter
42
+ @return_type = return_type
43
+ end
44
+
45
+ def eql?(another)
46
+ another.is_a?(FunctionType) &&
47
+ context == another.context &&
48
+ required_parameters == another.required_parameters &&
49
+ optional_parameters == another.optional_parameters &&
50
+ required_keyword_parameters.to_set == another.required_keyword_parameters.to_set &&
51
+ optional_keyword_parameters.to_set == another.optional_keyword_parameters.to_set &&
52
+ keyword_rest_parameter == another.keyword_rest_parameter &&
53
+ rest_parameter == another.rest_parameter &&
54
+ post_parameters == another.post_parameters &&
55
+ block_parameter == another.block_parameter &&
56
+ return_type == another.return_type
57
+ end
58
+
59
+ def hash
60
+ [
61
+ self.class.name,
62
+ context,
63
+ return_type,
64
+ required_parameters,
65
+ optional_parameters,
66
+ rest_parameter,
67
+ post_parameters,
68
+ required_keyword_parameters,
69
+ optional_keyword_parameters,
70
+ keyword_rest_parameter,
71
+ block_parameter,
72
+ ].hash
73
+ end
74
+
75
+ # @param namespace [YARD::CodeObjects::Base]
76
+ # @return [UnionType]
77
+ def change_root(namespace)
78
+ self.class.new(
79
+ context: context&.change_root(namespace),
80
+ return_type: return_type.change_root(namespace),
81
+ required_parameters: required_parameters.map { |param| param.change_root(namespace) },
82
+ optional_parameters: optional_parameters.map { |param| param.change_root(namespace) },
83
+ rest_parameter: rest_parameter&.change_root(namespace),
84
+ post_parameters: post_parameters.map { |param| param.change_root(namespace) },
85
+ required_keyword_parameters: required_keyword_parameters.map { |name, param| [name, param.change_root(namespace)] },
86
+ optional_keyword_parameters: required_keyword_parameters.map { |name, param| [name, param.change_root(namespace)] },
87
+ keyword_rest_parameter: keyword_rest_parameter&.change_root(namespace),
88
+ block_parameter: block_parameter&.change_root(namespace),
89
+ )
90
+ end
91
+
92
+ # @param registry [Registry]
93
+ # @return [Array<Store::Objects::Base>]
94
+ def resolve(registry)
95
+ []
96
+ end
97
+
98
+ def method_type_signature
99
+ params_str = all_parameters_to_s
100
+ (params_str.empty? ? ': ' : "(#{params_str}): ") + "#{return_type}"
101
+ end
102
+
103
+ def to_s
104
+ params_str = all_parameters_to_s
105
+ (params_str.empty? ? '' : "(#{params_str}) -> ") + "#{return_type}"
106
+ end
107
+
108
+ # @return [self]
109
+ def map(&block)
110
+ self.class.new(
111
+ context: context&.map(&block),
112
+ return_type: return_type.map(&block),
113
+ required_parameters: required_parameters.map { |param| param.map(&block) },
114
+ optional_parameters: optional_parameters.map { |param| param.map(&block) },
115
+ rest_parameter: rest_parameter&.map(&block),
116
+ post_parameters: post_parameters.map { |param| param.map(&block) },
117
+ required_keyword_parameters: required_keyword_parameters.map { |name, param| [name, param.map(&block)] },
118
+ optional_keyword_parameters: required_keyword_parameters.map { |name, param| [name, param.map(&block)] },
119
+ keyword_rest_parameter: keyword_rest_parameter&.map(&block),
120
+ block_parameter: block_parameter&.map(&block),
121
+ )
122
+ end
123
+
124
+ private
125
+
126
+ def all_parameters_to_s
127
+ [
128
+ required_parameters_to_s,
129
+ optional_parameters_to_s,
130
+ rest_parameter_to_s,
131
+ post_parameters_to_s,
132
+ keyword_parameters_to_s,
133
+ keyword_rest_parameter_to_s,
134
+ block_parameter_to_s
135
+ ].reject { |str| str.empty? }.join(', ')
136
+ end
137
+
138
+ def required_parameters_to_s
139
+ required_parameters.map { |type| type.to_s }.join(', ')
140
+ end
141
+
142
+ def optional_parameters_to_s
143
+ optional_parameters.map { |type| "?#{type}" }.join(', ')
144
+ end
145
+
146
+ def required_keyword_parameters_to_s
147
+ return '' if required_keyword_parameters.empty?
148
+ required_keyword_parameters.map { |(name, type)| "#{name}: #{type}" }.join(', ')
149
+ end
150
+
151
+ def optional_keyword_parameters_to_s
152
+ return '' if optional_keyword_parameters.empty?
153
+ optional_keyword_parameters.map { |(name, type)| "?#{name}: #{type}" }.join(', ')
154
+ end
155
+
156
+ def post_parameters_to_s
157
+ post_parameters.map { |type| type.to_s }.join(', ')
158
+ end
159
+
160
+ def rest_parameter_to_s
161
+ rest_parameter ? "*#{rest_parameter}" : ''
162
+ end
163
+
164
+ def keyword_rest_parameter_to_s
165
+ keyword_rest_parameter ? "**#{keyword_rest_parameter}" : ''
166
+ end
167
+
168
+ def block_parameter_to_s
169
+ block_parameter ? "&#{block_parameter}" : ''
170
+ end
171
+ end
172
+ end
173
+ end
174
+ end