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,18 @@
1
+ module Yoda
2
+ module Store
3
+ module Query
4
+ class FindMetaClass < Base
5
+ # @param path [String, Model::Path, Model::ScopedPath]
6
+ # @return [Objects::NamespaceObject, nil]
7
+ def find(path)
8
+ constant = FindConstant.new(registry).find(path)
9
+ if constant && meta_class = registry.find(Objects::MetaClassObject.address_of(constant.path))
10
+ meta_class
11
+ else
12
+ nil
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,74 @@
1
+ module Yoda
2
+ module Store
3
+ module Query
4
+ class FindMethod < Base
5
+ # @param namespace [Objects::Namespace]
6
+ # @param method_name [String, Regexp]
7
+ # @param visibility [Array<Symbol>, nil]
8
+ # @return [Objects::MethodObject, nil]
9
+ def find(namespace, method_name, visibility: nil)
10
+ lazy_select(namespace, method_name, visibility: visibility).first
11
+ end
12
+
13
+ # @param namespace [Objects::Namespace]
14
+ # @param method_name [String, Regexp]
15
+ # @param visibility [Array<Symbol>, nil]
16
+ # @return [Array<Objects::MethodObject>]
17
+ def select(namespace, method_name, visibility: nil)
18
+ lazy_select(namespace, method_name, visibility: nil).to_a
19
+ end
20
+
21
+ private
22
+
23
+ # @param namespace [Objects::Namespace]
24
+ # @param expected [String, Regexp]
25
+ # @param visibility [Array<Symbol>, nil]
26
+ # @return [Enumerator<Objects::MethodObject>]
27
+ def lazy_select(namespace, expected, visibility: nil)
28
+ visibility ||= %i(public private protected)
29
+ Enumerator.new do |yielder|
30
+ met = Set.new
31
+
32
+ all_method_addresses(namespace).each do |address|
33
+ name = Objects::MethodObject.name_of_path(address)
34
+ if match_name?(name, expected)
35
+ next if met.include?(name)
36
+ if el = registry.find(address)
37
+ met.add(name)
38
+ yielder << el if visibility.include?(el.visibility)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ # @param namespace [Objects::Namespace]
46
+ # @return [Enumerator<Objects::MethodObject>]
47
+ def all_method_addresses(namespace)
48
+ Enumerator.new do |yielder|
49
+ Associators::AssociateAncestors.new(registry).associate(namespace)
50
+ namespace.ancestors.each do |ancestor|
51
+ ancestor.instance_method_addresses.each do |address|
52
+ yielder << address
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ # @param name [String]
59
+ # @param expected_name_or_pattern [String, Regexp]
60
+ # @return [true, false]
61
+ def match_name?(name, expected_name_or_pattern)
62
+ case expected_name_or_pattern
63
+ when String
64
+ name == expected_name_or_pattern
65
+ when Regexp
66
+ name.match?(expected_name_or_pattern)
67
+ else
68
+ fail ArgumentError, expected_name_or_pattern
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,43 @@
1
+ module Yoda
2
+ module Store
3
+ module Query
4
+ class FindSignature < Base
5
+ # @param namespace [Objects::NamespaceObject]
6
+ # @param method_name [String, Regexp]
7
+ # @param visibility [Array<Symbol>, nil]
8
+ # @return [Array<Objects::MethodObject>]
9
+ def select(namespace, method_name, visibility: nil)
10
+ FindMethod.new(registry).select(namespace, method_name, visibility: visibility).map { |el| build(namespace, el) }.flatten
11
+ end
12
+
13
+ private
14
+
15
+ # @param receiver [Store::Objects::NamespaceObject]
16
+ # @param method_object [Store::Objects::MethodObject]
17
+ # @return [Array<FunctionSignatures::Base>]
18
+ def build(receiver, method_object)
19
+ if constructor = try_to_build_constructor(receiver, method_object)
20
+ [constructor]
21
+ elsif method_object.overloads.empty?
22
+ [Model::FunctionSignatures::Method.new(method_object)]
23
+ else
24
+ method_object.overloads.map { |overload| Model::FunctionSignatures::Overload.new(method_object, overload) }
25
+ end
26
+ end
27
+
28
+ # @param receiver [Store::Objects::NamespaceObject]
29
+ # @param method_object [Store::Objects::MethodObject]
30
+ # @return [FunctionSignatures::Constructor, nil]
31
+ def try_to_build_constructor(receiver, method_object)
32
+ if method_object.path == 'Class#new' && receiver.is_a?(Store::Objects::MetaClassObject) && receiver.path != 'Class'
33
+ base_class = registry.find(receiver.base_class_address) || return
34
+ initialize_object = FindMethod.new(registry).find(base_class, 'initialize') || return
35
+ Model::FunctionSignatures::Constructor.new(base_class, initialize_object)
36
+ else
37
+ nil
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,67 @@
1
+ require 'yard'
2
+ require 'ruby-progressbar'
3
+
4
+ module Yoda
5
+ module Store
6
+ class Registry
7
+ # @return [Adapters::LmdbAdapter, nil]
8
+ attr_reader :adapter
9
+
10
+ # @param adapter [Adapters::LmdbAdapter]
11
+ attr_writer :adapter
12
+
13
+ # @return [Objects::PatchSet]
14
+ attr_reader :patch_set
15
+
16
+ def initialize(adapter = nil)
17
+ @patch_set = Objects::PatchSet.new
18
+ @adapter = adapter
19
+ end
20
+
21
+ # @param path [String]
22
+ # @return [Objects::Base, nil]
23
+ def find(path)
24
+ if adapter&.exist?(path)
25
+ patch_set.patch(adapter.get(path))
26
+ else
27
+ patch_set.find(path)
28
+ end
29
+ end
30
+
31
+ # @param patch [Patch]
32
+ def add_patch(patch)
33
+ patch_set.register(patch)
34
+ end
35
+
36
+ # @param path [String]
37
+ # @return [true, false]
38
+ def has_key?(path)
39
+ adapter&.exists?(path) || patch_set.has_key?(path)
40
+ end
41
+
42
+ # Store patch set data to the database.
43
+ # old data in the database are discarded.
44
+ # @param progress [true, false]
45
+ def compress_and_save(progress: false)
46
+ return unless adapter
47
+ el_keys = patch_set.keys
48
+ bar = ProgressBar.create(format: " %c/%C |%w>%i| %e ", total: el_keys.length) if progress
49
+
50
+ data = Enumerator.new do |yielder|
51
+ el_keys.each { |key| yielder << [key, patch_set.find(key)] }
52
+ end
53
+
54
+ adapter.batch_write(data, bar)
55
+ adapter.sync
56
+ STDERR.puts "saved #{el_keys.length} keys."
57
+ @patch_set = Objects::PatchSet.new
58
+ end
59
+
60
+ private
61
+
62
+ def keys
63
+ Set.new(adapter&.keys.map(&:to_s) || []).union(patch_set.keys)
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,260 @@
1
+ require 'yard'
2
+
3
+ module Yoda
4
+ module Store
5
+ class YardImporter
6
+ # @return [Objects::Patch]
7
+ attr_reader :patch
8
+
9
+ # @return [String, nil]
10
+ attr_reader :root_path
11
+
12
+ # @param file [String]
13
+ # @param root_path [String, nil]
14
+ # @return [Objects::Patch]
15
+ def self.import(file, root_path: nil)
16
+ store = YARD::RegistryStore.new
17
+ store.load(file)
18
+ root_path ||= File.expand_path('..', file)
19
+ new(file, root_path: root_path).import(store.values).patch
20
+ end
21
+
22
+ # @param id [String]
23
+ def initialize(id, root_path: nil)
24
+ @patch = Objects::Patch.new(id)
25
+ @root_path = root_path
26
+ @registered = Set.new
27
+ end
28
+
29
+ # @param values [Array<YARD::CodeObjects::Base>]
30
+ # @return [self]
31
+ def import(values)
32
+ values.each do |el|
33
+ register(el)
34
+ end
35
+ self
36
+ end
37
+
38
+ # @param code_object [YARD::CodeObjects::Base]
39
+ def register(code_object)
40
+ return if @registered.member?(code_object.path)
41
+ @registered.add(code_object.path)
42
+ register(code_object.parent) if code_object.parent && !code_object.parent.root?
43
+
44
+ new_objects = begin
45
+ case code_object.type
46
+ when :root
47
+ convert_root_object(code_object)
48
+ when :class
49
+ convert_class_object(code_object)
50
+ when :module
51
+ convert_module_object(code_object)
52
+ when :classvariable
53
+ # convert_class_variable_object(code_object)
54
+ when :method
55
+ convert_method_object(code_object)
56
+ when :macro
57
+ # convert_macro_object(code_object)
58
+ when :constant
59
+ convert_constant_object(code_object)
60
+ when :proxy
61
+ create_proxy_module(code_object)
62
+ else
63
+ fail ArgumentError, 'Unsupported type code object'
64
+ end
65
+ end
66
+
67
+ register_to_parent_proxy(code_object) if code_object.parent && code_object.parent.type == :proxy
68
+ [new_objects].flatten.compact.each { |new_object| patch.register(new_object) }
69
+ end
70
+
71
+ private
72
+
73
+ # @param code_object [::YARD::CodeObjects::NamespaceObject]
74
+ # @return [Objects::ClassObject]
75
+ def convert_root_object(code_object)
76
+ # @todo Add meta class for main object.
77
+ Objects::ClassObject.new(
78
+ path: 'Object',
79
+ document: code_object.docstring.to_s,
80
+ tag_list: code_object.tags.map { |tag| convert_tag(tag, '') },
81
+ sources: code_object.files.map(&method(:convert_source)),
82
+ primary_source: code_object[:current_file_has_comments] ? convert_source(code_object.files.first) : nil,
83
+ instance_method_addresses: code_object.meths(included: false, scope: :instance).map(&:path),
84
+ mixin_addresses: code_object.instance_mixins.map { |mixin| mixin.path },
85
+ constant_addresses: (code_object.children.select{ |child| %i(constant module class).include?(child.type) }.map { |constant| constant.path } + ['Object']).uniq,
86
+ )
87
+ end
88
+
89
+ # @param code_object [::YARD::CodeObjects::ConstantObject]
90
+ # @return [Objects::ValueObject]
91
+ def convert_constant_object(code_object)
92
+ Objects::ValueObject.new(
93
+ path: code_object.path,
94
+ document: code_object.docstring.to_s,
95
+ tag_list: code_object.tags.map { |tag| convert_tag(tag, code_object.namespace.path) },
96
+ sources: code_object.files.map(&method(:convert_source)),
97
+ primary_source: code_object[:current_file_has_comments] ? convert_source(code_object.files.first) : nil,
98
+ value: code_object.value,
99
+ )
100
+ end
101
+
102
+ # @param code_object [::YARD::CodeObjects::MethodObject]
103
+ # @return [Objects::MethodObject, (Objects::MethodObject, Object::ClassObject)]
104
+ def convert_method_object(code_object)
105
+ if code_object.namespace.root?
106
+ # @todo Remove root oriented method path from Object namespace
107
+ method_object = Objects::MethodObject.new(
108
+ path: "Object#{code_object.sep}#{code_object.name}",
109
+ document: code_object.docstring.to_s,
110
+ tag_list: code_object.tags.map { |tag| convert_tag(tag, code_object.namespace.path) },
111
+ overloads: code_object.tags(:overload).map { |tag| convert_overload_tag(tag, code_object.namespace.path) },
112
+ sources: code_object.files.map(&method(:convert_source)),
113
+ primary_source: code_object[:current_file_has_comments] ? convert_source(code_object.files.first) : nil,
114
+ parameters: code_object.parameters,
115
+ visibility: :private,
116
+ )
117
+ object_object = Objects::ClassObject.new(
118
+ path: 'Object',
119
+ instance_method_addresses: ["Object#{code_object.sep}#{code_object.name}"],
120
+ )
121
+ [method_object, object_object]
122
+ else
123
+ Objects::MethodObject.new(
124
+ path: code_object.path,
125
+ document: code_object.docstring.to_s,
126
+ tag_list: code_object.tags.map { |tag| convert_tag(tag, code_object.namespace.path) },
127
+ overloads: code_object.tags(:overload).map { |tag| convert_overload_tag(tag, code_object.namespace.path) },
128
+ sources: code_object.files.map(&method(:convert_source)),
129
+ primary_source: code_object[:current_file_has_comments] ? convert_source(code_object.files.first) : nil,
130
+ parameters: code_object.parameters,
131
+ visibility: code_object.visibility,
132
+ )
133
+ end
134
+ end
135
+
136
+ # @param code_object [::YARD::CodeObjects::ModuleObject]
137
+ # @return [Array<Objects::ModuleObject, Objects::MetaClassObject>]
138
+ def convert_module_object(code_object)
139
+ module_object = Objects::ModuleObject.new(
140
+ path: code_object.path,
141
+ document: code_object.docstring.to_s,
142
+ tag_list: code_object.tags.map { |tag| convert_tag(tag, code_object.path) },
143
+ sources: code_object.files.map(&method(:convert_source)),
144
+ primary_source: code_object[:current_file_has_comments] ? convert_source(code_object.files.first) : nil,
145
+ instance_method_addresses: code_object.meths(included: false, scope: :instance).map(&:path),
146
+ mixin_addresses: code_object.instance_mixins.map { |mixin| mixin.path },
147
+ constant_addresses: code_object.children.select{ |child| %i(constant module class).include?(child.type) }.map { |constant| constant.path },
148
+ )
149
+
150
+ meta_class_object = Objects::MetaClassObject.new(
151
+ path: code_object.path,
152
+ sources: code_object.files.map(&method(:convert_source)),
153
+ primary_source: code_object[:current_file_has_comments] ? convert_source(code_object.files.first) : nil,
154
+ instance_method_addresses: code_object.meths(included: false, scope: :class).map(&:path),
155
+ mixin_addresses: code_object.instance_mixins.map { |mixin| mixin.path },
156
+ )
157
+
158
+ [module_object, meta_class_object]
159
+ end
160
+
161
+ # @param code_object [::YARD::CodeObjects::ClassObject]
162
+ # @return [Array<Objects::ClassObject, Objects::MetaClassObject>]
163
+ def convert_class_object(code_object)
164
+ class_object = Objects::ClassObject.new(
165
+ path: code_object.path,
166
+ document: code_object.docstring.to_s,
167
+ tag_list: code_object.tags.map { |tag| convert_tag(tag, code_object.path) },
168
+ sources: code_object.files.map(&method(:convert_source)),
169
+ primary_source: code_object[:current_file_has_comments] ? convert_source(code_object.files.first) : nil,
170
+ instance_method_addresses: code_object.meths(included: false, scope: :instance).map(&:path),
171
+ mixin_addresses: code_object.instance_mixins.map { |mixin| mixin.path },
172
+ constant_addresses: code_object.children.select{ |child| %i(constant module class).include?(child.type) }.map { |constant| constant.path },
173
+ superclass_path: code_object.superclass&.path == 'Qnil' ? nil : code_object.superclass&.path,
174
+ )
175
+
176
+ meta_class_object = Objects::MetaClassObject.new(
177
+ path: code_object.path,
178
+ sources: code_object.files.map(&method(:convert_source)),
179
+ primary_source: code_object[:current_file_has_comments] ? convert_source(code_object.files.first) : nil,
180
+ instance_method_addresses: code_object.meths(included: false, scope: :class).map(&:path),
181
+ mixin_addresses: code_object.class_mixins.map { |mixin| mixin.path },
182
+ )
183
+
184
+ [class_object, meta_class_object]
185
+ end
186
+
187
+ # @param tag [::YARD::Tags::Tag]
188
+ # @param namespace [String]
189
+ # @return [Objects::Tag]
190
+ def convert_tag(tag, namespace)
191
+ Objects::Tag.new(tag_name: tag.tag_name, name: tag.name, yard_types: tag.types, text: tag.text, lexical_scope: convert_to_lexical_scope(namespace))
192
+ end
193
+
194
+ # @param tag [::YARD::Tags::OverloadTag]
195
+ # @param namespace [String]
196
+ # @return [Objects::Tag]
197
+ def convert_overload_tag(tag, namespace)
198
+ Objects::Overload.new(name: tag.name.to_s, tag_list: tag.tags.map { |tag| convert_tag(tag, namespace) }, document: tag.docstring.to_s, parameters: tag.parameters)
199
+ end
200
+
201
+ # @param namespace [String]
202
+ # @return [Array<String>]
203
+ def convert_to_lexical_scope(namespace)
204
+ path = Model::Path.new(namespace)
205
+ ((path.to_s.empty? ? [] : [path]) + path.parent_paths).map(&:to_s)
206
+ end
207
+
208
+ # @param symbol [Symbol]
209
+ # @return [Symbol]
210
+ def convert_yard_object_type(type)
211
+ case type
212
+ when :constant
213
+ :value
214
+ else
215
+ type
216
+ end
217
+ end
218
+
219
+ # @param code_object [::YARD::CodeObjects::Proxy]
220
+ # @return [Array<Objects::ModuleObject>]
221
+ def create_proxy_module(code_object)
222
+ module_object = Objects::ModuleObject.new(
223
+ path: code_object.path,
224
+ document: '',
225
+ tag_list: [],
226
+ sources: [],
227
+ primary_source: nil,
228
+ instance_method_addresses: [],
229
+ mixin_addresses: [],
230
+ constant_addresses: [],
231
+ )
232
+
233
+ meta_class_object = Objects::MetaClassObject.new(
234
+ path: code_object.path,
235
+ sources: [],
236
+ primary_source: nil,
237
+ instance_method_addresses: [],
238
+ mixin_addresses: [],
239
+ )
240
+
241
+ [module_object, meta_class_object]
242
+ end
243
+
244
+ # @param code_object [::YARD::CodeObjects::Base]
245
+ # @return [vaid]
246
+ def register_to_parent_proxy(code_object)
247
+ proxy_module = patch.find(code_object.parent.path)
248
+ proxy_module.instance_method_addresses.push(code_object.path) if code_object.type == :method
249
+ proxy_module.constant_addresses.push(code_object.path) if [:class, :module, :proxy].include?(code_object.type)
250
+ end
251
+
252
+ # @param source [(String, Integer)]
253
+ # @return [(String, Integer, Integer)]
254
+ def convert_source(source)
255
+ file, line = source
256
+ [root_path ? File.expand_path(file, root_path) : file, line, 0]
257
+ end
258
+ end
259
+ end
260
+ end