Class: Solargraph::Workspace::Gemspecs
- Inherits:
-
Object
- Object
- Solargraph::Workspace::Gemspecs
- Includes:
- Logging
- Defined in:
- lib/solargraph/workspace/gemspecs.rb
Overview
Manages determining which gemspecs are available in a workspace
Constant Summary
Constants included from Logging
Logging::DEFAULT_LOG_LEVEL, Logging::LOG_LEVELS
Instance Attribute Summary collapse
-
#directory ⇒ Object
readonly
Returns the value of attribute directory.
-
#preferences ⇒ Object
readonly
Returns the value of attribute preferences.
Class Method Summary collapse
Instance Method Summary collapse
-
#all_gemspecs_from_bundle ⇒ Array<Gem::Specification, Bundler::LazySpecification, Bundler::StubSpecification>
Returns all gemspecs directly depended on by this workspace’s bundle (does not include transitive dependencies).
- #fetch_dependencies(gemspec, out: $stderr) ⇒ Array<Gem::Specification>
- #find_gem(name, version = nil, out: $stderr) ⇒ Gem::Specification?
-
#initialize(directory, preferences: []) ⇒ Gemspecs
constructor
A new instance of Gemspecs.
-
#resolve_require(require) ⇒ ::Array<Gem::Specification>?
Take the path given to a ‘require’ statement in a source file and return the Gem::Specifications which will be brought into scope with it, so we can load pins for them.
- #stdlib_dependencies(stdlib_name) ⇒ Array<String>
Methods included from Logging
Constructor Details
#initialize(directory, preferences: []) ⇒ Gemspecs
Returns a new instance of Gemspecs.
16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
# File 'lib/solargraph/workspace/gemspecs.rb', line 16 def initialize directory, preferences: [] # @todo an issue with both external bundles and the potential # preferences feature is that bundler gives you a 'clean' # rubygems environment with only the specified versions # installed. Possible alternatives: # # *) prompt the user to run solargraph outside of bundler # and treat all bundles as external # *) reinstall the needed gems dynamically each time # *) manipulate the rubygems/bundler environment @directory = directory && File.absolute_path(directory) # @todo implement preferences as a config-exposed feature @preferences = preferences end |
Instance Attribute Details
#directory ⇒ Object (readonly)
Returns the value of attribute directory.
12 13 14 |
# File 'lib/solargraph/workspace/gemspecs.rb', line 12 def directory @directory end |
#preferences ⇒ Object (readonly)
Returns the value of attribute preferences.
12 13 14 |
# File 'lib/solargraph/workspace/gemspecs.rb', line 12 def preferences @preferences end |
Class Method Details
.gem_specification_cache ⇒ Hash{Gem::Specification, Bundler::LazySpecification, Bundler::StubSpecification => Gem::Specification}
159 160 161 |
# File 'lib/solargraph/workspace/gemspecs.rb', line 159 def self.gem_specification_cache @gem_specification_cache ||= {} end |
Instance Method Details
#all_gemspecs_from_bundle ⇒ Array<Gem::Specification, Bundler::LazySpecification, Bundler::StubSpecification>
Returns all gemspecs directly depended on by this workspace’s bundle (does not include transitive dependencies).
147 148 149 150 151 152 153 154 155 156 |
# File 'lib/solargraph/workspace/gemspecs.rb', line 147 def all_gemspecs_from_bundle return [] unless directory @all_gemspecs_from_bundle ||= if in_this_bundle? all_gemspecs_from_this_bundle else all_gemspecs_from_external_bundle end end |
#fetch_dependencies(gemspec, out: $stderr) ⇒ Array<Gem::Specification>
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/solargraph/workspace/gemspecs.rb', line 119 def fetch_dependencies gemspec, out: $stderr all_gemspecs_from_bundle # @type [Hash{String => Gem::Specification}] deps_so_far = {} # @param runtime_dep [Gem::Dependency] # @param deps [Hash{String => Gem::Specification}] gem_dep_gemspecs = only_runtime_dependencies(gemspec).each_with_object(deps_so_far) do |runtime_dep, deps| dep = find_gem(runtime_dep.name, runtime_dep.requirement) next unless dep fetch_dependencies(dep, out: out).each { |sub_dep| deps[sub_dep.name] ||= sub_dep } deps[dep.name] ||= dep end # RBS tracks implicit dependencies, like how the YAML standard # library implies pulling in the psych library. stdlib_deps = RbsMap::StdlibMap.stdlib_dependencies(gemspec.name, gemspec.version) || [] stdlib_dep_gemspecs = stdlib_deps.map { |dep| find_gem(dep['name'], dep['version']) }.compact (gem_dep_gemspecs.values.compact + stdlib_dep_gemspecs).uniq(&:name) end |
#find_gem(name, version = nil, out: $stderr) ⇒ Gem::Specification?
102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/solargraph/workspace/gemspecs.rb', line 102 def find_gem name, version = nil, out: $stderr # @sg-ignore flow sensitive typing should be able to handle redefinition specish = all_gemspecs_from_bundle.find { |specish| specish.name == name && specish.version == version } return to_gem_specification specish if specish # @sg-ignore flow sensitive typing should be able to handle redefinition specish = all_gemspecs_from_bundle.find { |specish| specish.name == name } # @sg-ignore flow sensitive typing needs to create separate ranges for postfix if return to_gem_specification specish if specish resolve_gem_ignoring_local_bundle name, version, out: out end |
#resolve_require(require) ⇒ ::Array<Gem::Specification>?
Take the path given to a ‘require’ statement in a source file and return the Gem::Specifications which will be brought into scope with it, so we can load pins for them.
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/solargraph/workspace/gemspecs.rb', line 37 def resolve_require require return nil if require.empty? # This is added in the parser when it sees 'Bundler.require' - # see https://bundler.io/guides/bundler_setup.html ' # # @todo handle different arguments to Bundler.require return auto_required_gemspecs_from_bundler if require == 'bundler/require' # Determine gem name based on the require path file = "lib/#{require}.rb" spec_with_path = Gem::Specification.find_by_path(file) all_gemspecs = all_gemspecs_from_bundle gem_names_to_try = [ spec_with_path&.name, require.tr('/', '-'), require.split('/').first ].compact.uniq # @param gem_name [String] gem_names_to_try.each do |gem_name| # @sg-ignore Unresolved call to == on Boolean gemspec = all_gemspecs.find { |gemspec| gemspec.name == gem_name } # @sg-ignore flow sensitive typing should be able to handle redefinition return [gemspec_or_preference(gemspec)] if gemspec begin gemspec = Gem::Specification.find_by_name(gem_name) # @sg-ignore flow sensitive typing should be able to handle redefinition return [gemspec_or_preference(gemspec)] if gemspec rescue Gem::MissingSpecError logger.debug do "Require path #{require} could not be resolved to a gem via find_by_path or guess of #{gem_name}" end end # look ourselves just in case this is hanging out somewhere # that find_by_path doesn't index gemspec = all_gemspecs.find do |spec| spec = to_gem_specification(spec) unless spec.respond_to?(:files) # @sg-ignore Translate to something flow sensitive typing understands spec&.files&.any? { |gemspec_file| file == gemspec_file } end # @sg-ignore flow sensitive typing should be able to handle redefinition return [gemspec_or_preference(gemspec)] if gemspec end nil end |
#stdlib_dependencies(stdlib_name) ⇒ Array<String>
92 93 94 95 |
# File 'lib/solargraph/workspace/gemspecs.rb', line 92 def stdlib_dependencies stdlib_name deps = RbsMap::StdlibMap.stdlib_dependencies(stdlib_name, nil) || [] deps.map { |dep| dep['name'] }.compact end |