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,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
|