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.
- 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,36 @@
|
|
|
1
|
+
module Yoda
|
|
2
|
+
class Server
|
|
3
|
+
class DefinitionProvider
|
|
4
|
+
# @type ClientInfo
|
|
5
|
+
attr_reader :client_info
|
|
6
|
+
|
|
7
|
+
# @param client_info [ClientInfo]
|
|
8
|
+
def initialize(client_info)
|
|
9
|
+
@client_info = client_info
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# @param uri [String]
|
|
13
|
+
# @param position [{Symbol => Integer}]
|
|
14
|
+
# @param include_declaration [Boolean]
|
|
15
|
+
def provide(uri, position, include_declaration = false)
|
|
16
|
+
source = client_info.file_store.get(uri)
|
|
17
|
+
location = Parsing::Location.of_language_server_protocol_position(line: position[:line], character: position[:character])
|
|
18
|
+
|
|
19
|
+
node_worker = Evaluation::CurrentNodeExplain.new(client_info.registry, source, location)
|
|
20
|
+
references = node_worker.defined_files
|
|
21
|
+
references.map { |(path, line, column)| create_location(path, line, column) }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# @param path [String]
|
|
25
|
+
# @param line [Integer]
|
|
26
|
+
# @param column [Integer]
|
|
27
|
+
def create_location(path, line, column)
|
|
28
|
+
location = Parsing::Location.new(row: line - 1, column: column)
|
|
29
|
+
LSP::Interface::Location.new(
|
|
30
|
+
uri: client_info.uri_of_path(path),
|
|
31
|
+
range: LSP::Interface::Range.new(Parsing::Range.new(location, location).to_language_server_protocol_range),
|
|
32
|
+
)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'ostruct'
|
|
2
|
+
|
|
3
|
+
module Yoda
|
|
4
|
+
class Server
|
|
5
|
+
class Deserializer
|
|
6
|
+
def initialize
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# @param params [Hash]
|
|
10
|
+
def deserialize(params)
|
|
11
|
+
Hash[params.map { |key, value| [snakenize(key), deserialize_value(value)] }]
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# @param params [any]
|
|
15
|
+
def deserialize_value(value)
|
|
16
|
+
return deserialize(value) if value.is_a?(Hash)
|
|
17
|
+
return value.map { |el| deserialize_value(el) } if value.is_a?(Enumerable)
|
|
18
|
+
value
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# @param str [Symbol]
|
|
22
|
+
def snakenize(str)
|
|
23
|
+
str.to_s.gsub(/([A-Z])/, '_\1').downcase.to_sym
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module Yoda
|
|
2
|
+
class Server
|
|
3
|
+
class HoverProvider
|
|
4
|
+
attr_reader :client_info
|
|
5
|
+
|
|
6
|
+
# @param client_info [ClientInfo]
|
|
7
|
+
def initialize(client_info)
|
|
8
|
+
@client_info = client_info
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# @param uri [String]
|
|
12
|
+
# @param position [{Symbol => Integer}]
|
|
13
|
+
def request_hover(uri, position)
|
|
14
|
+
source = client_info.file_store.get(uri)
|
|
15
|
+
location = Parsing::Location.of_language_server_protocol_position(line: position[:line], character: position[:character])
|
|
16
|
+
|
|
17
|
+
node_worker = Evaluation::CurrentNodeExplain.new(client_info.registry, source, location)
|
|
18
|
+
|
|
19
|
+
current_node_signature = node_worker.current_node_signature
|
|
20
|
+
create_hover(current_node_signature) if current_node_signature
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# @param signature [Evaluation::NodeSignature]
|
|
24
|
+
def create_hover(signature)
|
|
25
|
+
LSP::Interface::Hover.new(
|
|
26
|
+
contents: signature.descriptions.map { |value| create_hover_text(value) },
|
|
27
|
+
range: LSP::Interface::Range.new(signature.node_range.to_language_server_protocol_range),
|
|
28
|
+
)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# @param description [Evaluation::Descriptions::Base]
|
|
32
|
+
# @return [String]
|
|
33
|
+
def create_hover_text(description)
|
|
34
|
+
description.to_markdown
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
module Yoda
|
|
2
|
+
class Server
|
|
3
|
+
class SignatureProvider
|
|
4
|
+
attr_reader :client_info
|
|
5
|
+
|
|
6
|
+
# @param client_info [ClientInfo]
|
|
7
|
+
def initialize(client_info)
|
|
8
|
+
@client_info = client_info
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# @param uri [String]
|
|
12
|
+
# @param position [{Symbol => Integer}]
|
|
13
|
+
def provide(uri, position)
|
|
14
|
+
source = client_info.file_store.get(uri)
|
|
15
|
+
location = Parsing::Location.of_language_server_protocol_position(line: position[:line], character: position[:character])
|
|
16
|
+
cut_source = Parsing::SourceCutter.new(source, location).error_recovered_source
|
|
17
|
+
|
|
18
|
+
signature_worker = Evaluation::SignatureDiscovery.new(client_info.registry, cut_source, location)
|
|
19
|
+
|
|
20
|
+
functions = signature_worker.method_candidates
|
|
21
|
+
create_signature_help(functions)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# @param code_objects [Array<Model::FunctionSignatures::Base>]
|
|
25
|
+
def create_signature_help(functions)
|
|
26
|
+
signatures = functions.map { |func| Model::Descriptions::FunctionDescription.new(func) }
|
|
27
|
+
LSP::Interface::SignatureHelp.new(
|
|
28
|
+
signatures: signatures.map { |signature| create_signature_info(signature) },
|
|
29
|
+
)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# @param signature [Evaluation::Descriptions::FunctionDescription]
|
|
33
|
+
def create_signature_info(signature)
|
|
34
|
+
LSP::Interface::SignatureInformation.new(
|
|
35
|
+
label: signature.title.to_s,
|
|
36
|
+
documentation: signature.to_markdown,
|
|
37
|
+
parameters: signature.parameter_names.map do |parameter|
|
|
38
|
+
LSP::Interface::ParameterInformation.new(
|
|
39
|
+
label: parameter,
|
|
40
|
+
)
|
|
41
|
+
end,
|
|
42
|
+
)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
data/lib/yoda/store.rb
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require 'yard'
|
|
2
|
+
|
|
3
|
+
module Yoda
|
|
4
|
+
module Store
|
|
5
|
+
require 'yoda/store/actions'
|
|
6
|
+
require 'yoda/store/adapters'
|
|
7
|
+
require 'yoda/store/project'
|
|
8
|
+
require 'yoda/store/registry'
|
|
9
|
+
require 'yoda/store/objects'
|
|
10
|
+
require 'yoda/store/query'
|
|
11
|
+
require 'yoda/store/yard_importer'
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module Yoda
|
|
2
|
+
module Store
|
|
3
|
+
module Actions
|
|
4
|
+
class ImportCoreLibrary
|
|
5
|
+
# @return [Registry]
|
|
6
|
+
attr_reader :registry
|
|
7
|
+
|
|
8
|
+
def initialize(registry)
|
|
9
|
+
@registry = registry
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def run
|
|
13
|
+
load_core_patches.each do |patch|
|
|
14
|
+
registry.add_patch(patch)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def load_core_patches
|
|
21
|
+
core_doc_files.map { |yardoc_file| YardImporter.import(yardoc_file) }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def core_doc_files
|
|
25
|
+
%W(.yoda/sources/ruby-#{RUBY_VERSION}/.yardoc .yoda/sources/ruby-#{RUBY_VERSION}/.yardoc-stdlib).map { |path| File.expand_path(path, '~') }.select { |path| File.exist?(path) }
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
require 'open3'
|
|
2
|
+
|
|
3
|
+
module Yoda
|
|
4
|
+
module Store
|
|
5
|
+
module Actions
|
|
6
|
+
class ImportGems
|
|
7
|
+
# @return [Registry]
|
|
8
|
+
attr_reader :registry
|
|
9
|
+
|
|
10
|
+
# @return [Array<Bundler::LazySpecification>]
|
|
11
|
+
attr_reader :gem_specs
|
|
12
|
+
|
|
13
|
+
# @param registry [Registry]
|
|
14
|
+
# @param gem_specs [Array<Bundler::LazySpecification>]
|
|
15
|
+
def initialize(registry, gem_specs)
|
|
16
|
+
@registry = registry
|
|
17
|
+
@gem_specs = gem_specs
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# @return [void]
|
|
21
|
+
def run
|
|
22
|
+
create_dependency_docs
|
|
23
|
+
gem_specs.map do |gem|
|
|
24
|
+
if yardoc_file = yardoc_file_for_gem(gem)
|
|
25
|
+
if patch = load_yardoc(yardoc_file, gem_path_for(gem))
|
|
26
|
+
registry.add_patch(patch)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def create_dependency_docs
|
|
35
|
+
gem_specs.each do |gem|
|
|
36
|
+
if yardoc_file_for_gem(gem)
|
|
37
|
+
STDERR.puts "Gem docs for #{gem.name} #{gem.version} already exist"
|
|
38
|
+
next
|
|
39
|
+
end
|
|
40
|
+
STDERR.puts "Building gem docs for #{gem.name} #{gem.version}"
|
|
41
|
+
begin
|
|
42
|
+
o, e = Open3.capture2e("yard gems #{gem.name} #{gem.version}")
|
|
43
|
+
STDERR.puts o unless o.empty?
|
|
44
|
+
if e.success?
|
|
45
|
+
STDERR.puts "Done building gem docs for #{gem.name} #{gem.version}"
|
|
46
|
+
else
|
|
47
|
+
STDERR.puts "Failed to build #{gem.name} #{gem.version}"
|
|
48
|
+
end
|
|
49
|
+
rescue => ex
|
|
50
|
+
STDERR.puts ex
|
|
51
|
+
STDERR.puts ex.backtrace
|
|
52
|
+
STDERR.puts "Failed to build #{gem.name} #{gem.version}"
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# @param gem [Bundler::LazySpecification]
|
|
58
|
+
# @return [String, nil]
|
|
59
|
+
def yardoc_file_for_gem(gem)
|
|
60
|
+
YARD::Registry.yardoc_file_for_gem(gem.name, gem.version)
|
|
61
|
+
rescue Bundler::BundlerError => ex
|
|
62
|
+
STDERR.puts ex
|
|
63
|
+
STDERR.puts ex.backtrace
|
|
64
|
+
nil
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# @param yardoc_file [String]
|
|
68
|
+
# @param gem_source_path [String]
|
|
69
|
+
# @return [Objects::Patch, nil]
|
|
70
|
+
def load_yardoc(yardoc_file, gem_source_path)
|
|
71
|
+
begin
|
|
72
|
+
YardImporter.import(yardoc_file, root_path: gem_source_path)
|
|
73
|
+
rescue => ex
|
|
74
|
+
STDERR.puts ex
|
|
75
|
+
STDERR.puts ex.backtrace
|
|
76
|
+
STDERR.puts "Failed to load #{yardoc_file}"
|
|
77
|
+
nil
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# @param gem [Bundler::LazySpecification]
|
|
82
|
+
# @return [String, nil]
|
|
83
|
+
def gem_path_for(gem)
|
|
84
|
+
if spec = Gem.source_index.find_name(gem.name).first
|
|
85
|
+
spec.full_gem_path
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
module Yoda
|
|
2
|
+
module Store
|
|
3
|
+
module Actions
|
|
4
|
+
class ReadFile
|
|
5
|
+
# @return [Registry]
|
|
6
|
+
attr_reader :registry
|
|
7
|
+
|
|
8
|
+
# @return [String]
|
|
9
|
+
attr_reader :file
|
|
10
|
+
|
|
11
|
+
# @param registry [Registry]
|
|
12
|
+
# @param file [String]
|
|
13
|
+
# @return [void]
|
|
14
|
+
def self.run(registry, file, root_path: nil)
|
|
15
|
+
self.new(registry, file, root_path: root_path).run
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# @param registry [Registry]
|
|
19
|
+
# @param file [String]
|
|
20
|
+
def initialize(registry, file, root_path: nil)
|
|
21
|
+
@registry = registry
|
|
22
|
+
@file = file
|
|
23
|
+
@root_path = root_path
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# @return [void]
|
|
27
|
+
def run
|
|
28
|
+
YARD::Registry.clear
|
|
29
|
+
YARD.parse([file])
|
|
30
|
+
patch = YardImporter.new(file).import(YARD::Registry.all + [YARD::Registry.root]).patch
|
|
31
|
+
registry.add_patch(patch)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module Yoda
|
|
2
|
+
module Store
|
|
3
|
+
module Actions
|
|
4
|
+
class ReadProjectFiles
|
|
5
|
+
# @return [Registry]
|
|
6
|
+
attr_reader :registry
|
|
7
|
+
|
|
8
|
+
# @return [String]
|
|
9
|
+
attr_reader :root_path
|
|
10
|
+
|
|
11
|
+
def initialize(registry, root_path)
|
|
12
|
+
@registry = registry
|
|
13
|
+
@root_path = root_path
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def run
|
|
17
|
+
project_files.each { |file| ReadFile.run(registry, file) }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
# @return [Array<String>]
|
|
23
|
+
def project_files
|
|
24
|
+
Dir.chdir(root_path) { Dir.glob("{lib,app}/**/*.rb\0ext/**/*.c\0.yoda/*.rb").map { |name| File.expand_path(name, root_path) } }
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module Yoda
|
|
2
|
+
module Store
|
|
3
|
+
module Adapters
|
|
4
|
+
require 'yoda/store/adapters/base'
|
|
5
|
+
require 'yoda/store/adapters/leveldb_adapter'
|
|
6
|
+
require 'yoda/store/adapters/lmdb_adapter'
|
|
7
|
+
|
|
8
|
+
# @return [Base.class]
|
|
9
|
+
def self.default_adapter_class
|
|
10
|
+
LmdbAdapter
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
module Yoda
|
|
2
|
+
module Store
|
|
3
|
+
module Adapters
|
|
4
|
+
# @abstract
|
|
5
|
+
class Base
|
|
6
|
+
# @abstract
|
|
7
|
+
def self.for(path)
|
|
8
|
+
fail NotImplementedError
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# @abstract
|
|
12
|
+
def self.type
|
|
13
|
+
fail NotImplementedError
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# @abstract
|
|
17
|
+
def get(address)
|
|
18
|
+
fail NotImplementedError
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# @abstract
|
|
22
|
+
def put(address, object)
|
|
23
|
+
fail NotImplementedError
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# @abstract
|
|
27
|
+
def delete(address)
|
|
28
|
+
fail NotImplementedError
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# @abstract
|
|
32
|
+
def exist?(address)
|
|
33
|
+
fail NotImplementedError
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# @abstract
|
|
37
|
+
def keys
|
|
38
|
+
fail NotImplementedError
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# @abstract
|
|
42
|
+
def stats
|
|
43
|
+
fail NotImplementedError
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# @abstract
|
|
47
|
+
def sync
|
|
48
|
+
fail NotImplementedError
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# @abstract
|
|
52
|
+
def clear
|
|
53
|
+
fail NotImplementedError
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
require 'leveldb'
|
|
2
|
+
require 'json'
|
|
3
|
+
|
|
4
|
+
module Yoda
|
|
5
|
+
module Store
|
|
6
|
+
module Adapters
|
|
7
|
+
class LeveldbAdapter < Base
|
|
8
|
+
class << self
|
|
9
|
+
def for(path)
|
|
10
|
+
@pool ||= {}
|
|
11
|
+
@pool[path] || (@pool[path] = new(path))
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def type
|
|
15
|
+
:leveldb
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# @param path [String] represents the path to store db.
|
|
20
|
+
def initialize(path)
|
|
21
|
+
@path = path
|
|
22
|
+
@db = LevelDB::DB.new(path, compression: true)
|
|
23
|
+
|
|
24
|
+
at_exit { @db.closed? || @db.close }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# @param address [String]
|
|
28
|
+
# @return [any]
|
|
29
|
+
def get(address)
|
|
30
|
+
JSON.load(@db.get(address.to_s), symbolize_names: true)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# @param address [String]
|
|
34
|
+
# @param object [Object]
|
|
35
|
+
# @return [void]
|
|
36
|
+
def put(address, object)
|
|
37
|
+
@db.put(address.to_s, object.to_json)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# @param data [Enumerator<(String, Object)>]
|
|
41
|
+
# @param bar [ProgressBar, nil]
|
|
42
|
+
def batch_write(data, bar)
|
|
43
|
+
data.each do |(k, v)|
|
|
44
|
+
@db.put(k, v)
|
|
45
|
+
bar&.increment
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# @param address [String]
|
|
50
|
+
# @return [void]
|
|
51
|
+
def delete(address)
|
|
52
|
+
@db.delete(address.to_s)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# @param address [String]
|
|
56
|
+
# @return [true, false]
|
|
57
|
+
def exist?(address)
|
|
58
|
+
@db.exists?(address.to_s)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# @return [Array<String>]
|
|
62
|
+
def keys
|
|
63
|
+
@db.keys
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def stats
|
|
67
|
+
@db.stats
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def clear
|
|
71
|
+
@db.destroy!
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def sync
|
|
75
|
+
# nop
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|