yoda-language-server 0.9.0 → 0.10.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 (90) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/client/vscode/package-lock.json +6 -6
  4. data/client/vscode/src/check-versions.ts +5 -11
  5. data/client/vscode/src/install-tools.ts +1 -1
  6. data/lib/yoda/cli/analyze_deps.rb +46 -25
  7. data/lib/yoda/id_mask.rb +84 -0
  8. data/lib/yoda/model/descriptions/require_path_description.rb +45 -0
  9. data/lib/yoda/model/descriptions.rb +1 -0
  10. data/lib/yoda/model/node_signatures/node.rb +9 -1
  11. data/lib/yoda/model/values/literal_value.rb +3 -0
  12. data/lib/yoda/parsing/location.rb +9 -0
  13. data/lib/yoda/services/loadable_path_resolver.rb +33 -0
  14. data/lib/yoda/services.rb +1 -0
  15. data/lib/yoda/store/actions/read_project_files.rb +9 -7
  16. data/lib/yoda/store/adapters/gdbm_adapter/namespace_accessor.rb +1 -1
  17. data/lib/yoda/store/adapters/memory_adapter.rb +1 -1
  18. data/lib/yoda/store/objects/libraries_status.rb +1 -1
  19. data/lib/yoda/store/objects/library/core.rb +8 -0
  20. data/lib/yoda/store/objects/library/gem.rb +14 -3
  21. data/lib/yoda/store/objects/library/path_resolvable.rb +29 -0
  22. data/lib/yoda/store/objects/library/std.rb +9 -0
  23. data/lib/yoda/store/objects/library.rb +1 -0
  24. data/lib/yoda/store/objects/patch.rb +1 -1
  25. data/lib/yoda/store/objects/patch_set.rb +2 -2
  26. data/lib/yoda/store/project/dependency.rb +22 -4
  27. data/lib/yoda/store/project/file_finder.rb +20 -0
  28. data/lib/yoda/store/project.rb +2 -0
  29. data/lib/yoda/store/registry/cache.rb +2 -2
  30. data/lib/yoda/store/registry/composer.rb +9 -7
  31. data/lib/yoda/store/registry/index.rb +14 -10
  32. data/lib/yoda/store/registry/library_registry.rb +1 -1
  33. data/lib/yoda/store/registry.rb +1 -1
  34. data/lib/yoda/typing/constant_resolver/code_query.rb +25 -0
  35. data/lib/yoda/typing/constant_resolver/query.rb +12 -1
  36. data/lib/yoda/typing/constant_resolver.rb +13 -8
  37. data/lib/yoda/typing/inferencer/load_resolver.rb +37 -0
  38. data/lib/yoda/typing/inferencer/tracer.rb +32 -0
  39. data/lib/yoda/typing/inferencer.rb +3 -2
  40. data/lib/yoda/typing/node_info.rb +5 -0
  41. data/lib/yoda/typing/tree/{defined.rb → ask_defined.rb} +3 -2
  42. data/lib/yoda/typing/tree/base.rb +65 -20
  43. data/lib/yoda/typing/tree/begin.rb +5 -5
  44. data/lib/yoda/typing/tree/block_call.rb +26 -0
  45. data/lib/yoda/typing/tree/case.rb +8 -19
  46. data/lib/yoda/typing/tree/class_tree.rb +10 -18
  47. data/lib/yoda/typing/tree/conditional_loop.rb +15 -0
  48. data/lib/yoda/typing/tree/constant.rb +19 -0
  49. data/lib/yoda/typing/tree/constant_assignment.rb +2 -2
  50. data/lib/yoda/typing/tree/ensure.rb +17 -0
  51. data/lib/yoda/typing/tree/for.rb +7 -0
  52. data/lib/yoda/typing/tree/hash_tree.rb +32 -0
  53. data/lib/yoda/typing/tree/if.rb +10 -5
  54. data/lib/yoda/typing/tree/interpolation_text.rb +21 -0
  55. data/lib/yoda/typing/tree/literal.rb +8 -36
  56. data/lib/yoda/typing/tree/literal_inferable.rb +48 -0
  57. data/lib/yoda/typing/tree/local_exit.rb +15 -0
  58. data/lib/yoda/typing/tree/logical_assignment.rb +5 -5
  59. data/lib/yoda/typing/tree/logical_operator.rb +6 -5
  60. data/lib/yoda/typing/tree/method_def.rb +41 -0
  61. data/lib/yoda/typing/tree/method_inferable.rb +51 -0
  62. data/lib/yoda/typing/tree/module_tree.rb +7 -20
  63. data/lib/yoda/typing/tree/multiple_assignment.rb +6 -10
  64. data/lib/yoda/typing/tree/namespace_inferable.rb +20 -0
  65. data/lib/yoda/typing/tree/rescue.rb +18 -0
  66. data/lib/yoda/typing/tree/rescue_clause.rb +42 -0
  67. data/lib/yoda/typing/tree/self.rb +2 -1
  68. data/lib/yoda/typing/tree/send.rb +8 -60
  69. data/lib/yoda/typing/tree/send_inferable.rb +89 -0
  70. data/lib/yoda/typing/tree/singleton_class_tree.rb +24 -0
  71. data/lib/yoda/typing/tree/singleton_method_def.rb +41 -0
  72. data/lib/yoda/typing/tree/super.rb +9 -2
  73. data/lib/yoda/typing/tree/variable.rb +5 -10
  74. data/lib/yoda/typing/tree/variable_assignment.rb +11 -8
  75. data/lib/yoda/typing/tree/yield.rb +9 -2
  76. data/lib/yoda/typing/tree.rb +55 -22
  77. data/lib/yoda/typing.rb +1 -0
  78. data/lib/yoda/version.rb +1 -1
  79. data/lib/yoda.rb +1 -0
  80. metadata +25 -13
  81. data/lib/yoda/typing/inferencer/ast_traverser.rb +0 -408
  82. data/lib/yoda/typing/tree/block.rb +0 -12
  83. data/lib/yoda/typing/tree/const.rb +0 -12
  84. data/lib/yoda/typing/tree/escape.rb +0 -12
  85. data/lib/yoda/typing/tree/hash_body.rb +0 -36
  86. data/lib/yoda/typing/tree/literal_with_interpolation.rb +0 -21
  87. data/lib/yoda/typing/tree/method.rb +0 -43
  88. data/lib/yoda/typing/tree/rescue_body.rb +0 -12
  89. data/lib/yoda/typing/tree/singleton_method.rb +0 -47
  90. data/lib/yoda/typing/tree/while.rb +0 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 52ade5f050c0172759a16bc736b42a0f81217b4efb51a6dd926f6c54c53464dc
4
- data.tar.gz: c1e2b2439b0a22948d01cc5886321e9f6fe6f83142aead6d8466b32e7a54b8b7
3
+ metadata.gz: ac5417cb4b65a5825e8cbbafc5e7c2396dd676f8c9be6635b6ae9721a58d9d4e
4
+ data.tar.gz: 93c16d20eeef7a4af4483df0313814529adeefa8f0561e1fa96f72627730eb5a
5
5
  SHA512:
6
- metadata.gz: 84c53ecfb0696eadb924907812d9614d8df2f71b1b9bc8deac0b92dd2d70180aeb708731f75d96508acace9c6bfb027f2b88d509af0dbd0d42ba7418146c8af5
7
- data.tar.gz: a38c732bc5cfa9eee8d2e343d328073e978eae350bf4806e8d8ffc203e0b4ec0061e7fec7df0925375f656a2aa078fd106dc1b695cc87b70c298969bf49a1386
6
+ metadata.gz: 57ab04ba88f6d0047c00ef4a0c92531ddc8a7966dcf10b93c16d01152ea62981bba5eb40d8a94dcaf1c6eea015f710fb44c5a1eca45bc40614b51c5f79325d9e
7
+ data.tar.gz: 7af4d13dd31562946ee5c3dd7e57e5c95b14450dce1b8ab8a9e1719a4b53067f384f069cb522b027158cca2407e9c47d84e86dcf604f940d3cea1cf47318a00d
data/CHANGELOG.md CHANGED
@@ -1,4 +1,9 @@
1
1
  ## Unreleased
2
+ ## v0.10.0 - 2022-03-28
3
+
4
+ * Support go to definition on path of require clause
5
+ * Fix inference failure on code with constant node and super node
6
+
2
7
  ## v0.9.0 - 2022-03-22
3
8
 
4
9
  * Support progress report of server initialization
@@ -1472,9 +1472,9 @@
1472
1472
  }
1473
1473
  },
1474
1474
  "node_modules/minimist": {
1475
- "version": "1.2.5",
1476
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
1477
- "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
1475
+ "version": "1.2.6",
1476
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
1477
+ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
1478
1478
  "dev": true
1479
1479
  },
1480
1480
  "node_modules/mkdirp": {
@@ -3784,9 +3784,9 @@
3784
3784
  }
3785
3785
  },
3786
3786
  "minimist": {
3787
- "version": "1.2.5",
3788
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
3789
- "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
3787
+ "version": "1.2.6",
3788
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
3789
+ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
3790
3790
  "dev": true
3791
3791
  },
3792
3792
  "mkdirp": {
@@ -10,8 +10,11 @@ interface CheckResult {
10
10
  }
11
11
 
12
12
  export async function checkVersions(): Promise<CheckResult> {
13
- const { stdout } = await asyncExec("gem list --both --exact yoda-language-server")
14
- const [localVersion, remoteVersion] = parseGemList(stdout)
13
+ const { stdout: localStdout } = await asyncExec("gem list --local --exact yoda-language-server")
14
+ const localVersion = extractVersion(localStdout)
15
+
16
+ const { stdout: remoteStdout } = await asyncExec("gem list --remote --no-prerelease --exact yoda-language-server")
17
+ const remoteVersion = extractVersion(remoteStdout)
15
18
 
16
19
  return {
17
20
  shouldUpdate: shouldUpdate(localVersion, remoteVersion),
@@ -32,15 +35,6 @@ function shouldUpdate(localVersion: string, remoteVersion: string): boolean {
32
35
  return cmp(localVersion, "<", remoteVersion)
33
36
  }
34
37
 
35
- function parseGemList(stdout: string): [string, string] {
36
- const [local, remote] = stdout.split("*** REMOTE GEMS ***")
37
-
38
- const localVersion = extractVersion(local)
39
- const remoteVersion = extractVersion(remote)
40
-
41
- return [localVersion, remoteVersion]
42
- }
43
-
44
38
  function extractVersion(text: string): string {
45
39
  const lines = text.split("\n")
46
40
  for (const line of lines) {
@@ -44,7 +44,7 @@ export async function promptForInstallTool(update: boolean, newVersion?: string)
44
44
  const newVersionLabel = newVersion ? ` (${newVersion})` : ''
45
45
 
46
46
  const message = update ?
47
- `A newer version of yoda${newVersionLabel} is updatable.` :
47
+ `A newer version of yoda${newVersionLabel} is available.` :
48
48
  'yoda command is not available. Please install.'
49
49
 
50
50
  const selected = await window.showInformationMessage(message, ...choises)
@@ -16,7 +16,7 @@ module Yoda
16
16
 
17
17
  # @param root_path [String]
18
18
  def initialize(root_path)
19
- @root_path = root_path
19
+ @root_path = File.expand_path(root_path)
20
20
  end
21
21
 
22
22
  # @return [Array<Yoda::Store::Objects::Library::Gem>]
@@ -28,6 +28,7 @@ module Yoda
28
28
  {
29
29
  path: root_path,
30
30
  dependencies: gems.map(&:to_h),
31
+ autoload_dependency_ids: autoload_gem_ids,
31
32
  }
32
33
  end
33
34
 
@@ -45,39 +46,47 @@ module Yoda
45
46
  end
46
47
  end
47
48
 
48
- # @return [Array<Bundler::LazySpecification>, nil]
49
+ # @return [Array<String>]
50
+ def autoload_gem_ids
51
+ if has_gemfile?
52
+ gems.map(&:id)
53
+ else
54
+ []
55
+ end
56
+ end
57
+
58
+ # @return [Array<Bundler::LazySpecification, Gem::Specification>, nil]
49
59
  def gem_specs
50
60
  @gem_specs ||= begin
51
- Dir.chdir(root_path) do
52
- with_unbundled_env do
53
- # Suppress bundler outputs to stdout.
54
- Bundler.ui = Bundler::UI::Silent.new
55
-
56
- Bundler.reset!
57
-
58
- if File.exists?("Gemfile")
59
- # Resolve dependencies of uninstalled gems and ensure remote sources are available.
60
- Bundler.definition.resolve_remotely!
61
- spec_set = Bundler.definition.resolve
62
-
63
- if Gem::Version.new(Bundler::VERSION) >= Gem::Version.new('2.2.25')
64
- deps = Bundler.definition.requested_dependencies
65
- spec_set.materialize(deps).to_a
66
- else
67
- # For backward compatibility (Ref: https://github.com/rubygems/rubygems/pull/4788)
68
- deps = Bundler.definition.send(:requested_dependencies)
69
- missing = []
70
- materialized = spec_set.materialize(deps, missing)
71
- materialized.to_a + missing
72
- end
61
+ with_project_env do
62
+ if has_gemfile?
63
+ # Resolve dependencies of uninstalled gems and ensure remote sources are available.
64
+ Bundler.definition.resolve_remotely!
65
+ spec_set = Bundler.definition.resolve
66
+
67
+ if Gem::Version.new(Bundler::VERSION) >= Gem::Version.new('2.2.25')
68
+ deps = Bundler.definition.requested_dependencies
69
+ spec_set.materialize(deps).to_a
73
70
  else
74
- []
71
+ # For backward compatibility (Ref: https://github.com/rubygems/rubygems/pull/4788)
72
+ deps = Bundler.definition.send(:requested_dependencies)
73
+ missing = []
74
+ materialized = spec_set.materialize(deps, missing)
75
+
76
+ materialized.to_a + missing
75
77
  end
78
+ else
79
+ [] # Gem::Specification.latest_specs(true)
76
80
  end
77
81
  end
78
82
  end
79
83
  end
80
84
 
85
+ # @return [Boolean]
86
+ def has_gemfile?
87
+ File.exists?(File.expand_path("Gemfile", root_path))
88
+ end
89
+
81
90
  # @param [Gem::Specification]
82
91
  def metadata?(spec)
83
92
  spec.source.is_a?(Bundler::Source::Metadata)
@@ -88,6 +97,18 @@ module Yoda
88
97
  spec.source.is_a?(Bundler::Source::Path) && (File.expand_path(spec.source.path) == File.expand_path(root_path))
89
98
  end
90
99
 
100
+ def with_project_env
101
+ Dir.chdir(root_path) do
102
+ with_unbundled_env do
103
+ # Suppress bundler outputs to stdout.
104
+ Bundler.ui = Bundler::UI::Silent.new
105
+ Bundler.reset!
106
+
107
+ yield
108
+ end
109
+ end
110
+ end
111
+
91
112
  def with_unbundled_env(&block)
92
113
  if Bundler.respond_to?(:with_unbundled_env)
93
114
  Bundler.with_unbundled_env(&block)
@@ -0,0 +1,84 @@
1
+ require 'set'
2
+
3
+ module Yoda
4
+ class IdMask
5
+ # @return [Hash<Symbol>, nil]
6
+ attr_reader :pattern
7
+
8
+ # @param pattern [IdMask, Set<Symbol>, Array<Symbol>, Hash<Symbol>, nil]
9
+ # @return [IdMask]
10
+ def self.build(pattern)
11
+ if pattern.is_a?(IdMask)
12
+ pattern
13
+ elsif pattern.nil?
14
+ new(pattern)
15
+ elsif pattern.is_a?(Hash)
16
+ new(pattern.map { |k, v| [k.to_sym, v] }.to_h)
17
+ else
18
+ new(pattern.to_a.to_h { |id| [id.to_sym, nil] })
19
+ end
20
+ end
21
+
22
+ # @param pattern [Hash<Symbol>, nil]
23
+ def initialize(pattern)
24
+ fail TypeError, "pattern must be a Hash or nil" unless pattern.is_a?(Hash) || pattern.nil?
25
+ @pattern = pattern
26
+ end
27
+
28
+ # @param id [Symbol, String]
29
+ # @return [Boolean]
30
+ def cover?(id)
31
+ return true if any?
32
+ pattern.has_key?(id.to_sym)
33
+ end
34
+
35
+ # @param another [IdMasklia, Set<Symbol>, Array<Symbol>, Hash<Symbol>, nil]
36
+ # @return [IdMask]
37
+ def intersection(another)
38
+ another_mask = IdMask.build(another)
39
+ return another_mask if any?
40
+ return self if another_mask.any?
41
+
42
+ ids_intersection = covering_ids & another_mask.covering_ids
43
+
44
+ intersection_pattern = ids_intersection.map do |id|
45
+ [id, nesting_mask(id) & another_mask.nesting_mask(id)]
46
+ end.to_h
47
+
48
+ IdMask.build(intersection_pattern)
49
+ end
50
+
51
+ alias_method :&, :intersection
52
+
53
+ # @return [Boolean]
54
+ def any?
55
+ pattern.nil?
56
+ end
57
+
58
+ # @return [Set<Symbol>, nil]
59
+ def covering_ids
60
+ @covering_ids ||= begin
61
+ if any?
62
+ nil
63
+ else
64
+ Set.new(pattern.keys)
65
+ end
66
+ end
67
+ end
68
+
69
+ # @param id [String, Symbol]
70
+ # @return [IdMask]
71
+ def nesting_mask(id)
72
+ if pattern.is_a?(Hash)
73
+ IdMask.build(pattern[id.to_sym])
74
+ else
75
+ IdMask.build(nil)
76
+ end
77
+ end
78
+
79
+ # @return [Hash, nil]
80
+ def to_pattern
81
+ pattern&.map { |k, v| [k, v&.to_pattern] }&.to_h
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,45 @@
1
+ module Yoda
2
+ module Model
3
+ module Descriptions
4
+ # @abstract
5
+ class RequirePathDescription
6
+ # @return [String]
7
+ attr_reader :path
8
+
9
+ # @param path [String]
10
+ def initialize(path)
11
+ @path = path
12
+ end
13
+
14
+ # @abstract
15
+ # @return [String]
16
+ def title
17
+ path
18
+ end
19
+
20
+ # @abstract
21
+ # @return [String]
22
+ def sort_text
23
+ path
24
+ end
25
+
26
+ # @return [String]
27
+ def label
28
+ sort_text
29
+ end
30
+
31
+ # @abstract
32
+ # @return [String]
33
+ def to_markdown
34
+ path
35
+ end
36
+
37
+ # Return an LSP MarkedString content for description
38
+ # @return [String, Hash]
39
+ def markup_content
40
+ to_markdown
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -7,6 +7,7 @@ module Yoda
7
7
  require 'yoda/model/descriptions/value_description'
8
8
  require 'yoda/model/descriptions/word_description'
9
9
  require 'yoda/model/descriptions/node_description'
10
+ require 'yoda/model/descriptions/require_path_description'
10
11
  require 'yoda/model/descriptions/variable_description'
11
12
  end
12
13
  end
@@ -3,7 +3,15 @@ module Yoda
3
3
  module NodeSignatures
4
4
  class Node < Base
5
5
  def descriptions
6
- [node_type_description, *type_descriptions]
6
+ if node_info.require_paths.empty?
7
+ [node_type_description, *type_descriptions]
8
+ else
9
+ node_info.require_paths.map { |path| Descriptions::RequirePathDescription.new(path) }
10
+ end
11
+ end
12
+
13
+ def defined_files
14
+ node_info.require_paths.map { |path| [path, Parsing::Location.first_row, Parsing::Location.first_column] }
7
15
  end
8
16
  end
9
17
  end
@@ -11,6 +11,9 @@ module Yoda
11
11
  # @return [Base]
12
12
  attr_reader :value
13
13
 
14
+ # @return [Object]
15
+ attr_reader :literal
16
+
14
17
  # @param value [Base]
15
18
  # @param literal [Object]
16
19
  def initialize(value:, literal:)
@@ -17,6 +17,15 @@ module Yoda
17
17
  @column = column
18
18
  end
19
19
 
20
+ def self.first_row
21
+ 1
22
+ end
23
+
24
+ def self.first_column
25
+ 0
26
+ end
27
+
28
+
20
29
  # @param ast_location [Parser::Source::Map, Parser::Source::Range]
21
30
  # @return [Location, nil]
22
31
  def self.of_ast_location(ast_location)
@@ -0,0 +1,33 @@
1
+ module Yoda
2
+ module Services
3
+ class LoadablePathResolver
4
+ def initialize
5
+ end
6
+
7
+ # @param base_paths [Array<String>]
8
+ # @param pattern [String]
9
+ # @return [String, nil]
10
+ def find_loadable_path(base_paths, pattern)
11
+ # TODO: Support absolute path
12
+ return nil if File.absolute_path?(pattern)
13
+ return nil if pattern.start_with?("~/")
14
+ return nil if pattern.start_with?("./")
15
+ return nil if pattern.start_with?("../")
16
+
17
+ base_paths.each do |base_path|
18
+ path = File.join(base_path, pattern)
19
+
20
+ if File.extname(path).empty?
21
+ paths_with_suffix = ::Gem.suffixes.map { |suffix| path + suffix }
22
+ matched_path = paths_with_suffix.find { |path| File.file?(path) }
23
+ return matched_path if matched_path
24
+ else
25
+ return path if File.file?(path)
26
+ end
27
+ end
28
+
29
+ return nil
30
+ end
31
+ end
32
+ end
33
+ end
data/lib/yoda/services.rb CHANGED
@@ -4,6 +4,7 @@ module Yoda
4
4
  require 'yoda/services/current_node_explain'
5
5
  require 'yoda/services/comment_completion'
6
6
  require 'yoda/services/code_completion'
7
+ require 'yoda/services/loadable_path_resolver'
7
8
  require 'yoda/services/signature_discovery'
8
9
  end
9
10
  end
@@ -2,21 +2,23 @@ module Yoda
2
2
  module Store
3
3
  module Actions
4
4
  class ReadProjectFiles
5
+ # @return [Project]
6
+ attr_reader :project
7
+
5
8
  # @return [Registry]
6
9
  attr_reader :registry
7
10
 
8
- # @return [String]
9
- attr_reader :root_path
10
-
11
11
  # @param project [Project]
12
12
  # @return [ReadProjectFiles]
13
13
  def self.for_project(project)
14
- new(project.registry, project.root_path)
14
+ new(project, project.registry)
15
15
  end
16
16
 
17
- def initialize(registry, root_path)
17
+ # @param project [Project]
18
+ # @param registry [Project]
19
+ def initialize(project, registry)
20
+ @project = project
18
21
  @registry = registry
19
- @root_path = root_path
20
22
  end
21
23
 
22
24
  def run
@@ -35,7 +37,7 @@ module Yoda
35
37
 
36
38
  # @return [Array<String>]
37
39
  def project_files
38
- Dir.chdir(root_path) { Dir.glob(["{lib,app}/**/*.rb", "ext/**/*.c", ".yoda/*.rb"]).map { |name| File.expand_path(name, root_path) } }
40
+ project.project_source_paths
39
41
  end
40
42
  end
41
43
  end
@@ -20,7 +20,7 @@ module Yoda
20
20
 
21
21
  # @param address [String, Symbol]
22
22
  # @return [Object, nil]
23
- def get(address)
23
+ def get(address, **)
24
24
  JSON.load(database[build_key(address)], symbolize_names: true)
25
25
  end
26
26
 
@@ -28,7 +28,7 @@ module Yoda
28
28
 
29
29
  # @param address [String]
30
30
  # @return [any]
31
- def get(address)
31
+ def get(address, **)
32
32
  JSON.load(db[address.to_s], symbolize_names: true)
33
33
  end
34
34
 
@@ -10,7 +10,7 @@ module Yoda
10
10
  # @param dependency [Project::Dependency]
11
11
  # @return [Array<Object::Library::Core, Object::Library::Std, Object::Library::Gem>]
12
12
  def self.libraies_from_dependency(dependency)
13
- [dependency.core, dependency.std, *dependency.gems.select(&:installed?)]
13
+ [dependency.core, dependency.std, *dependency.autoload_gems.select(&:installed?)]
14
14
  end
15
15
 
16
16
  # @param libraries [Array<Library::Core, Library::Std, Library::Gem>]
@@ -1,3 +1,5 @@
1
+ require 'yoda/store/objects/library/path_resolvable'
2
+
1
3
  module Yoda
2
4
  module Store
3
5
  module Objects
@@ -42,6 +44,7 @@ module Yoda
42
44
  class Connected
43
45
  extend ConnectedDelegation
44
46
  include WithRegistry
47
+ include PathResolvable
45
48
 
46
49
  delegate_to_object :version
47
50
  delegate_to_object :id, :name, :doc_path, :to_h, :with_project_connection
@@ -64,6 +67,11 @@ module Yoda
64
67
  def registry_path
65
68
  VersionStore.for_current_version.registry_path_for_core
66
69
  end
70
+
71
+ # @return [Array<String>]
72
+ def require_paths
73
+ []
74
+ end
67
75
  end
68
76
  end
69
77
  end
@@ -1,18 +1,24 @@
1
+ require 'yoda/store/objects/library/path_resolvable'
2
+
1
3
  module Yoda
2
4
  module Store
3
5
  module Objects
4
6
  module Library
5
7
  class Gem
6
8
  include Serializable
9
+ include PathResolvable
7
10
 
8
11
  # @return [String]
9
12
  attr_reader :name, :version, :source_path, :full_gem_path, :doc_dir
10
13
 
14
+ # @return [Array<String>]
15
+ attr_reader :require_paths
16
+
11
17
  # @return [Symbol, nil]
12
18
  attr_reader :source_type
13
19
 
14
20
  class << self
15
- # @param spec [Bundler::LazySpecification]
21
+ # @param spec [Bundler::LazySpecification, Gem::Specification]
16
22
  def from_gem_spec(spec)
17
23
  if spec.respond_to?(:full_gem_path)
18
24
  # Installed
@@ -20,6 +26,7 @@ module Yoda
20
26
  name: spec.name,
21
27
  version: spec.version.version,
22
28
  source_path: spec.source.respond_to?(:path) ? spec.source.path : nil,
29
+ require_paths: spec.full_require_paths,
23
30
  full_gem_path: spec.full_gem_path,
24
31
  doc_dir: spec.doc_dir,
25
32
  source_type: source_type_of(spec.source),
@@ -30,6 +37,7 @@ module Yoda
30
37
  name: spec.name,
31
38
  version: spec.version.version,
32
39
  source_path: nil,
40
+ require_paths: [],
33
41
  full_gem_path: nil,
34
42
  doc_dir: nil,
35
43
  source_type: nil,
@@ -57,11 +65,12 @@ module Yoda
57
65
  end
58
66
  end
59
67
 
60
- def initialize(name:, version:, source_path:, full_gem_path:, doc_dir:, source_type:)
68
+ def initialize(name:, version:, source_path:, full_gem_path:, require_paths:, doc_dir:, source_type:)
61
69
  @name = name
62
70
  @version = version
63
71
  @source_path = source_path
64
72
  @full_gem_path = full_gem_path
73
+ @require_paths = require_paths
65
74
  @doc_dir = doc_dir
66
75
  @source_type = source_type&.to_sym
67
76
  end
@@ -80,6 +89,7 @@ module Yoda
80
89
  version: version,
81
90
  source_path: source_path,
82
91
  full_gem_path: full_gem_path,
92
+ require_paths: require_paths,
83
93
  doc_dir: doc_dir,
84
94
  source_type: source_type,
85
95
  }
@@ -103,9 +113,10 @@ module Yoda
103
113
  extend ConnectedDelegation
104
114
  include WithRegistry
105
115
 
106
- delegate_to_object :name, :version, :source_path, :full_gem_path, :doc_dir, :source_type
116
+ delegate_to_object :name, :version, :source_path, :full_gem_path, :doc_dir, :source_type, :require_paths
107
117
  delegate_to_object :id, :local?, :to_h, :installed?, :managed_by_rubygems?, :with_project_connection
108
118
  delegate_to_object :hash, :eql?, :==, :to_json, :derive
119
+ delegate_to_object :contain_requirable_file?, :find_requirable_file
109
120
 
110
121
  # @return [Gem]
111
122
  attr_reader :object
@@ -0,0 +1,29 @@
1
+ require 'yoda/store/objects/library/path_resolvable'
2
+
3
+ module Yoda
4
+ module Store
5
+ module Objects
6
+ module Library
7
+ module PathResolvable
8
+ # @abstract
9
+ # @return [Array<String>]
10
+ def require_paths
11
+ fail NotImplementedError
12
+ end
13
+
14
+ # @param relative_path [String]
15
+ # @return [Boolean]
16
+ def contain_requirable_file?(relative_path)
17
+ !!find_requirable_file(relative_path)
18
+ end
19
+
20
+ # @param relative_path [String]
21
+ # @return [String, nil]
22
+ def find_requirable_file(relative_path)
23
+ Services::LoadablePathResolver.new.find_loadable_path(require_paths, relative_path)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,3 +1,5 @@
1
+ require 'yoda/store/objects/library/path_resolvable'
2
+
1
3
  module Yoda
2
4
  module Store
3
5
  module Objects
@@ -42,6 +44,7 @@ module Yoda
42
44
  class Connected
43
45
  extend ConnectedDelegation
44
46
  include WithRegistry
47
+ include PathResolvable
45
48
 
46
49
  delegate_to_object :version
47
50
  delegate_to_object :id, :name, :doc_path, :to_h, :with_project_connection
@@ -64,6 +67,12 @@ module Yoda
64
67
  def registry_path
65
68
  VersionStore.for_current_version.registry_path_for_stdlib
66
69
  end
70
+
71
+ # @return [Array<String>]
72
+ def require_paths
73
+ # TODO: Calculate from registry
74
+ [File.join(VersionStore.for_current_version.ruby_source_path, "lib/")]
75
+ end
67
76
  end
68
77
  end
69
78
  end
@@ -6,6 +6,7 @@ module Yoda
6
6
  require 'yoda/store/objects/library/core'
7
7
  require 'yoda/store/objects/library/std'
8
8
  require 'yoda/store/objects/library/gem'
9
+ require 'yoda/store/objects/library/path_resolvable'
9
10
 
10
11
  class << self
11
12
  # @return [Core]
@@ -17,7 +17,7 @@ module Yoda
17
17
 
18
18
  # @param address [String, Symbol]
19
19
  # @return [Addressable, nil]
20
- def find(address)
20
+ def find(address, **)
21
21
  @registry[address.to_sym]
22
22
  end
23
23
  alias get find