solargraph 0.59.0.dev.2 → 0.59.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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/linting.yml +3 -1
  3. data/.github/workflows/plugins.yml +8 -2
  4. data/.github/workflows/rspec.yml +6 -40
  5. data/.github/workflows/typecheck.yml +2 -1
  6. data/.rubocop.yml +6 -1
  7. data/.rubocop_todo.yml +3 -0
  8. data/CHANGELOG.md +15 -0
  9. data/lib/solargraph/api_map/constants.rb +0 -1
  10. data/lib/solargraph/api_map/index.rb +6 -0
  11. data/lib/solargraph/api_map/store.rb +6 -0
  12. data/lib/solargraph/api_map.rb +20 -4
  13. data/lib/solargraph/complex_type/type_methods.rb +2 -1
  14. data/lib/solargraph/complex_type/unique_type.rb +2 -4
  15. data/lib/solargraph/complex_type.rb +1 -1
  16. data/lib/solargraph/doc_map.rb +370 -131
  17. data/lib/solargraph/gem_pins.rb +16 -17
  18. data/lib/solargraph/library.rb +44 -66
  19. data/lib/solargraph/logging.rb +0 -2
  20. data/lib/solargraph/parser/flow_sensitive_typing.rb +0 -2
  21. data/lib/solargraph/parser/parser_gem/class_methods.rb +0 -2
  22. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +0 -1
  23. data/lib/solargraph/pin/base.rb +0 -2
  24. data/lib/solargraph/pin/method.rb +3 -0
  25. data/lib/solargraph/pin/reference/type_alias.rb +16 -0
  26. data/lib/solargraph/pin/reference.rb +1 -0
  27. data/lib/solargraph/pin_cache.rb +66 -480
  28. data/lib/solargraph/position.rb +7 -4
  29. data/lib/solargraph/rbs_map/conversions.rb +18 -18
  30. data/lib/solargraph/rbs_map.rb +2 -3
  31. data/lib/solargraph/shell.rb +163 -15
  32. data/lib/solargraph/source/chain.rb +3 -1
  33. data/lib/solargraph/source_map/mapper.rb +0 -2
  34. data/lib/solargraph/type_checker.rb +1 -2
  35. data/lib/solargraph/version.rb +1 -1
  36. data/lib/solargraph/workspace/config.rb +1 -1
  37. data/lib/solargraph/workspace/gemspecs.rb +2 -2
  38. data/lib/solargraph/workspace.rb +32 -129
  39. data/lib/solargraph/yard_map.rb +17 -18
  40. data/lib/solargraph/yardoc.rb +26 -33
  41. data/lib/solargraph.rb +2 -0
  42. data/solargraph.gemspec +2 -2
  43. metadata +6 -11
@@ -2,7 +2,6 @@
2
2
 
3
3
  require 'open3'
4
4
  require 'json'
5
- require 'yaml'
6
5
 
7
6
  module Solargraph
8
7
  # A workspace consists of the files in a project's directory and the
@@ -10,8 +9,6 @@ module Solargraph
10
9
  # in an associated Library or ApiMap.
11
10
  #
12
11
  class Workspace
13
- include Logging
14
-
15
12
  autoload :Config, 'solargraph/workspace/config'
16
13
  autoload :Gemspecs, 'solargraph/workspace/gemspecs'
17
14
  autoload :RequirePaths, 'solargraph/workspace/require_paths'
@@ -23,8 +20,7 @@ module Solargraph
23
20
  attr_reader :gemnames
24
21
  alias source_gems gemnames
25
22
 
26
- # @todo Remove '' and '*' special cases
27
- # @param directory [String]
23
+ # @param directory [String] TODO: Remove '' and '*' special cases
28
24
  # @param config [Config, nil]
29
25
  # @param server [Hash]
30
26
  def initialize directory = '', config = nil, server = {}
@@ -55,68 +51,6 @@ module Solargraph
55
51
  @config ||= Solargraph::Workspace::Config.new(directory)
56
52
  end
57
53
 
58
- # @param stdlib_name [String]
59
- #
60
- # @return [Array<String>]
61
- def stdlib_dependencies stdlib_name
62
- gemspecs.stdlib_dependencies(stdlib_name)
63
- end
64
-
65
- # @param out [IO, nil] output stream for logging
66
- # @param gemspec [Gem::Specification]
67
- # @return [Array<Gem::Specification>]
68
- def fetch_dependencies gemspec, out: $stderr
69
- gemspecs.fetch_dependencies(gemspec, out: out)
70
- end
71
-
72
- # @param require [String] The string sent to 'require' in the code to resolve, e.g. 'rails', 'bundler/require'
73
- # @return [Array<Gem::Specification>, nil]
74
- def resolve_require require
75
- gemspecs.resolve_require(require)
76
- end
77
-
78
- # @return [Solargraph::PinCache]
79
- def pin_cache
80
- @pin_cache ||= fresh_pincache
81
- end
82
-
83
- # @return [Environ]
84
- def global_environ
85
- # empty docmap, since the result needs to work in any possible
86
- # context here
87
- @global_environ ||= Convention.for_global(DocMap.new([], self, out: nil))
88
- end
89
-
90
- # @param gemspec [Gem::Specification]
91
- # @param out [StringIO, IO, nil] output stream for logging
92
- # @param rebuild [Boolean] whether to rebuild the pins even if they are cached
93
- #
94
- # @return [void]
95
- def cache_gem gemspec, out: nil, rebuild: false
96
- pin_cache.cache_gem(gemspec: gemspec, out: out, rebuild: rebuild)
97
- end
98
-
99
- # @param gemspec [Gem::Specification, Bundler::LazySpecification]
100
- # @param out [StringIO, IO, nil] output stream for logging
101
- #
102
- # @return [void]
103
- def uncache_gem gemspec, out: nil
104
- pin_cache.uncache_gem(gemspec, out: out)
105
- end
106
-
107
- # @return [Solargraph::PinCache]
108
- def fresh_pincache
109
- PinCache.new(rbs_collection_path: rbs_collection_path,
110
- rbs_collection_config_path: rbs_collection_config_path,
111
- yard_plugins: yard_plugins,
112
- directory: directory)
113
- end
114
-
115
- # @return [Array<String>]
116
- def yard_plugins
117
- @yard_plugins ||= global_environ.yard_plugins.sort.uniq
118
- end
119
-
120
54
  # @param level [Symbol]
121
55
  # @return [TypeChecker::Rules]
122
56
  def rules level
@@ -130,7 +64,6 @@ module Solargraph
130
64
  # @param sources [Array<Solargraph::Source>]
131
65
  # @return [Boolean] True if the source was added to the workspace
132
66
  def merge *sources
133
- # @sg-ignore Need to add nil check here
134
67
  unless directory == '*' || sources.all? { |source| source_hash.key?(source.filename) }
135
68
  # Reload the config to determine if a new source should be included
136
69
  @config = Solargraph::Workspace::Config.new(directory)
@@ -138,10 +71,9 @@ module Solargraph
138
71
 
139
72
  includes_any = false
140
73
  sources.each do |source|
141
- # @sg-ignore Need to add nil check here
142
74
  next unless directory == '*' || config.calculated.include?(source.filename)
143
75
 
144
- # @sg-ignore Need to add nil check here
76
+ # @sg-ignore Wrong argument type for Hash#[]=: arg0 expected String, received String, nil
145
77
  source_hash[source.filename] = source
146
78
  includes_any = true
147
79
  end
@@ -196,23 +128,6 @@ module Solargraph
196
128
  false
197
129
  end
198
130
 
199
- # True if the workspace contains at least one gemspec file.
200
- #
201
- # @return [Boolean]
202
- def gemspec?
203
- !gemspec_files.empty?
204
- end
205
-
206
- # Get an array of all gemspec files in the workspace.
207
- #
208
- # @return [Array<String>]
209
- def gemspec_files
210
- return [] if directory.empty? || directory == '*'
211
- @gemspec_files ||= Dir[File.join(directory, '**/*.gemspec')].select do |gs|
212
- config.allow? gs
213
- end
214
- end
215
-
216
131
  # @return [String, nil]
217
132
  def rbs_collection_path
218
133
  @rbs_collection_path ||= read_rbs_collection_path
@@ -220,11 +135,10 @@ module Solargraph
220
135
 
221
136
  # @return [String, nil]
222
137
  def rbs_collection_config_path
223
- @rbs_collection_config_path ||=
224
- unless directory.empty? || directory == '*'
225
- yaml_file = File.join(directory, 'rbs_collection.yaml')
226
- yaml_file if File.file?(yaml_file)
227
- end
138
+ @rbs_collection_config_path ||= unless directory.empty? || directory == '*'
139
+ yaml_file = File.join(directory, 'rbs_collection.yaml')
140
+ yaml_file if File.file?(yaml_file)
141
+ end
228
142
  end
229
143
 
230
144
  # @param name [String]
@@ -233,34 +147,7 @@ module Solargraph
233
147
  #
234
148
  # @return [Gem::Specification, nil]
235
149
  def find_gem name, version = nil, out: nil
236
- gemspecs.find_gem(name, version, out: out)
237
- end
238
-
239
- # @return [Array<Gem::Specification>]
240
- def all_gemspecs_from_bundle
241
- gemspecs.all_gemspecs_from_bundle
242
- end
243
-
244
- # @param out [StringIO, IO, nil] output stream for logging
245
- # @param rebuild [Boolean] whether to rebuild the pins even if they are cached
246
- # @return [void]
247
- def cache_all_for_workspace! out, rebuild: false
248
- PinCache.cache_core(out: out) unless PinCache.core? && !rebuild
249
-
250
- gem_specs = all_gemspecs_from_bundle
251
- # try any possible standard libraries, but be quiet about it
252
- stdlib_specs = pin_cache.possible_stdlibs.map { |stdlib| find_gem(stdlib, out: nil) }.compact
253
- specs = (gem_specs + stdlib_specs)
254
- specs.each do |spec|
255
- pin_cache.cache_gem(gemspec: spec, rebuild: rebuild, out: out) unless pin_cache.cached?(spec)
256
- end
257
- out&.puts "Documentation cached for all #{specs.length} gems."
258
-
259
- # do this after so that we prefer stdlib requires from gems,
260
- # which are likely to be newer and have more pins
261
- pin_cache.cache_all_stdlibs(out: out, rebuild: rebuild)
262
-
263
- out&.puts 'Documentation cached for core, standard library and gems.'
150
+ Gem::Specification.find_by_name(name, version)
264
151
  end
265
152
 
266
153
  # Synchronize the workspace from the provided updater.
@@ -271,9 +158,8 @@ module Solargraph
271
158
  source_hash[updater.filename] = source_hash[updater.filename].synchronize(updater)
272
159
  end
273
160
 
274
- # @sg-ignore Need to validate config
161
+ # @sg-ignore return type could not be inferred
275
162
  # @return [String]
276
- # @sg-ignore Need to validate config
277
163
  def command_path
278
164
  server['commandPath'] || 'solargraph'
279
165
  end
@@ -284,9 +170,29 @@ module Solargraph
284
170
  directory
285
171
  end
286
172
 
287
- # @return [Solargraph::Workspace::Gemspecs]
288
- def gemspecs
289
- @gemspecs ||= Solargraph::Workspace::Gemspecs.new(directory_or_nil)
173
+ # True if the workspace has a root Gemfile.
174
+ #
175
+ # @todo Handle projects with custom Bundler/Gemfile setups (see DocMap#gemspecs_required_from_bundler)
176
+ #
177
+ def gemfile?
178
+ directory && File.file?(File.join(directory, 'Gemfile'))
179
+ end
180
+
181
+ # True if the workspace contains at least one gemspec file.
182
+ #
183
+ # @return [Boolean]
184
+ def gemspec?
185
+ !gemspec_files.empty?
186
+ end
187
+
188
+ # Get an array of all gemspec files in the workspace.
189
+ #
190
+ # @return [Array<String>]
191
+ def gemspec_files
192
+ return [] if directory.empty? || directory == '*'
193
+ @gemspec_files ||= Dir[File.join(directory, '**/*.gemspec')].select do |gs|
194
+ config.allow? gs
195
+ end
290
196
  end
291
197
 
292
198
  private
@@ -307,10 +213,7 @@ module Solargraph
307
213
  source_hash.clear
308
214
  return if directory.empty? || directory == '*'
309
215
  size = config.calculated.length
310
- if config.max_files.positive? && (size > config.max_files)
311
- raise WorkspaceTooLargeError,
312
- "The workspace is too large to index (#{size} files, #{config.max_files} max)"
313
- end
216
+ raise WorkspaceTooLargeError, "The workspace is too large to index (#{size} files, #{config.max_files} max)" if config.max_files.positive? && size > config.max_files
314
217
  config.calculated.each do |filename|
315
218
  source_hash[filename] = Solargraph::Source.load(filename)
316
219
  rescue Errno::ENOENT => e
@@ -1,18 +1,17 @@
1
- # frozen_string_literal: true
2
-
3
- require 'yard'
4
- require 'solargraph/yard_tags'
5
-
6
- module Solargraph
7
- # The YardMap provides access to YARD documentation for the Ruby core, the
8
- # stdlib, and gems.
9
- #
10
- class YardMap
11
- class NoYardocError < StandardError; end
12
-
13
- autoload :Cache, 'solargraph/yard_map/cache'
14
- autoload :Mapper, 'solargraph/yard_map/mapper'
15
- autoload :Helpers, 'solargraph/yard_map/helpers'
16
- autoload :ToMethod, 'solargraph/yard_map/to_method'
17
- end
18
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'yard'
4
+ require 'solargraph/yard_tags'
5
+
6
+ module Solargraph
7
+ # The YardMap provides access to YARD documentation for the Ruby core, the
8
+ # stdlib, and gems.
9
+ #
10
+ class YardMap
11
+ class NoYardocError < StandardError; end
12
+
13
+ autoload :Cache, 'solargraph/yard_map/cache'
14
+ autoload :Mapper, 'solargraph/yard_map/mapper'
15
+ autoload :Helpers, 'solargraph/yard_map/helpers'
16
+ end
17
+ end
@@ -8,15 +8,15 @@ module Solargraph
8
8
  module Yardoc
9
9
  module_function
10
10
 
11
- # Build and save a gem's yardoc into a given path.
11
+ # Build and cache a gem's yardoc and return the path. If the cache already
12
+ # exists, do nothing and return the path.
12
13
  #
13
- # @param gem_yardoc_path [String] the path to the yardoc cache of a particular gem
14
- # @param yard_plugins [Array<String>]
14
+ # @param yard_plugins [Array<String>] The names of YARD plugins to use.
15
15
  # @param gemspec [Gem::Specification]
16
- #
17
- # @return [void]
18
- def build_docs gem_yardoc_path, yard_plugins, gemspec
19
- return if docs_built?(gem_yardoc_path)
16
+ # @return [String] The path to the cached yardoc.
17
+ def cache yard_plugins, gemspec
18
+ path = PinCache.yardoc_path gemspec
19
+ return path if cached?(gemspec)
20
20
 
21
21
  unless Dir.exist? gemspec.gem_dir
22
22
  # Can happen in at least some (old?) RubyGems versions when we
@@ -24,44 +24,37 @@ module Solargraph
24
24
  #
25
25
  # https://github.com/apiology/solargraph/actions/runs/17650140201/job/50158676842?pr=10
26
26
  Solargraph.logger.info { "Bad info from gemspec - #{gemspec.gem_dir} does not exist" }
27
- return
27
+ return path
28
28
  end
29
29
 
30
30
  Solargraph.logger.info "Caching yardoc for #{gemspec.name} #{gemspec.version}"
31
- cmd = "yardoc --db #{gem_yardoc_path} --no-output --plugin solargraph"
31
+ cmd = "yardoc --db #{path} --no-output --plugin solargraph"
32
32
  yard_plugins.each { |plugin| cmd << " --plugin #{plugin}" }
33
33
  Solargraph.logger.debug { "Running: #{cmd}" }
34
34
  # @todo set these up to run in parallel
35
- # @sg-ignore Our fill won't work properly due to an issue in
36
- # Callable#arity_matches? - see comment there
35
+ # @todo Is the chdir argument being used here?
36
+ # @sg-ignore Unrecognized keyword argument chdir to Open3.capture2e
37
37
  stdout_and_stderr_str, status = Open3.capture2e(current_bundle_env_tweaks, cmd, chdir: gemspec.gem_dir)
38
- return if status.success?
39
- Solargraph.logger.warn { "YARD failed running #{cmd.inspect} in #{gemspec.gem_dir}" }
40
- Solargraph.logger.info stdout_and_stderr_str
41
- end
42
-
43
- # @param gem_yardoc_path [String] the path to the yardoc cache of a particular gem
44
- # @param gemspec [Gem::Specification, Bundler::LazySpecification]
45
- # @param out [StringIO, IO, nil] where to log messages
46
- # @return [Array<Pin::Base>]
47
- def build_pins gem_yardoc_path, gemspec, out: $stderr
48
- yardoc = load!(gem_yardoc_path)
49
- YardMap::Mapper.new(yardoc, gemspec).map
38
+ unless status.success?
39
+ Solargraph.logger.warn { "YARD failed running #{cmd.inspect} in #{gemspec.gem_dir}" }
40
+ Solargraph.logger.info stdout_and_stderr_str
41
+ end
42
+ path
50
43
  end
51
44
 
52
45
  # True if the gem yardoc is cached.
53
46
  #
54
- # @param gem_yardoc_path [String]
55
- def docs_built? gem_yardoc_path
56
- yardoc = File.join(gem_yardoc_path, 'complete')
47
+ # @param gemspec [Gem::Specification]
48
+ def cached? gemspec
49
+ yardoc = File.join(PinCache.yardoc_path(gemspec), 'complete')
57
50
  File.exist?(yardoc)
58
51
  end
59
52
 
60
53
  # True if another process is currently building the yardoc cache.
61
54
  #
62
- # @param gem_yardoc_path [String] the path to the yardoc cache of a particular gem
63
- def processing? gem_yardoc_path
64
- yardoc = File.join(gem_yardoc_path, 'processing')
55
+ # @param gemspec [Gem::Specification]
56
+ def processing? gemspec
57
+ yardoc = File.join(PinCache.yardoc_path(gemspec), 'processing')
65
58
  File.exist?(yardoc)
66
59
  end
67
60
 
@@ -69,10 +62,10 @@ module Solargraph
69
62
  #
70
63
  # @note This method modifies the global YARD registry.
71
64
  #
72
- # @param gem_yardoc_path [String] the path to the yardoc cache of a particular gem
65
+ # @param gemspec [Gem::Specification]
73
66
  # @return [Array<YARD::CodeObjects::Base>]
74
- def load! gem_yardoc_path
75
- YARD::Registry.load! gem_yardoc_path
67
+ def load! gemspec
68
+ YARD::Registry.load! PinCache.yardoc_path gemspec
76
69
  YARD::Registry.all
77
70
  end
78
71
 
@@ -87,7 +80,7 @@ module Solargraph
87
80
  # @return [Hash{String => String}] a hash of environment variables to override
88
81
  def current_bundle_env_tweaks
89
82
  tweaks = {}
90
- # @sg-ignore Translate to something flow sensitive typing understands
83
+ # @sg-ignore Unresolved call to empty? on String, nil
91
84
  if ENV['BUNDLE_GEMFILE'] && !ENV['BUNDLE_GEMFILE'].empty?
92
85
  tweaks['BUNDLE_GEMFILE'] = File.expand_path(ENV['BUNDLE_GEMFILE'])
93
86
  end
data/lib/solargraph.rb CHANGED
@@ -83,6 +83,8 @@ module Solargraph
83
83
  return if type == :alias_target_missing && msg.include?('highline/compatibility.rb')
84
84
  # @sg-ignore flow sensitive typing needs to handle 'raise if'
85
85
  return if type == :alias_target_missing && msg.include?('lib/json/add/date.rb')
86
+ # @sg-ignore flow sensitive typing needs to handle 'raise if'
87
+ return if type == :alias_target_missing && msg.include?('rubocop-ast.rbs')
86
88
  # @todo :combine_with_visibility is not ready for prime time -
87
89
  # lots of disagreements found in practice that heuristics need
88
90
  # to be created for and/or debugging needs to resolve in pin
data/solargraph.gemspec CHANGED
@@ -28,7 +28,7 @@ Gem::Specification.new do |s|
28
28
  s.metadata['source_code_uri'] = 'https://github.com/castwide/solargraph'
29
29
  s.metadata['rubygems_mfa_required'] = 'true'
30
30
 
31
- s.required_ruby_version = '>= 3.0'
31
+ s.required_ruby_version = '>= 3.1'
32
32
 
33
33
  s.add_dependency 'ast', '~> 2.4.3'
34
34
  s.add_dependency 'backport', '~> 1.2'
@@ -44,7 +44,7 @@ Gem::Specification.new do |s|
44
44
  s.add_dependency 'ostruct', '~> 0.6'
45
45
  s.add_dependency 'parser', '~> 3.0'
46
46
  s.add_dependency 'prism', '~> 1.4'
47
- s.add_dependency 'rbs', ['>= 3.6.1', '<= 4.0.0.dev.5']
47
+ s.add_dependency 'rbs', '>= 3.10.0'
48
48
  s.add_dependency 'reverse_markdown', '~> 3.0'
49
49
  s.add_dependency 'rubocop', '~> 1.76'
50
50
  s.add_dependency 'thor', '~> 1.0'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solargraph
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.59.0.dev.2
4
+ version: 0.59.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fred Snyder
@@ -217,20 +217,14 @@ dependencies:
217
217
  requirements:
218
218
  - - ">="
219
219
  - !ruby/object:Gem::Version
220
- version: 3.6.1
221
- - - "<="
222
- - !ruby/object:Gem::Version
223
- version: 4.0.0.dev.5
220
+ version: 3.10.0
224
221
  type: :runtime
225
222
  prerelease: false
226
223
  version_requirements: !ruby/object:Gem::Requirement
227
224
  requirements:
228
225
  - - ">="
229
226
  - !ruby/object:Gem::Version
230
- version: 3.6.1
231
- - - "<="
232
- - !ruby/object:Gem::Version
233
- version: 4.0.0.dev.5
227
+ version: 3.10.0
234
228
  - !ruby/object:Gem::Dependency
235
229
  name: reverse_markdown
236
230
  requirement: !ruby/object:Gem::Requirement
@@ -733,6 +727,7 @@ files:
733
727
  - lib/solargraph/pin/reference/prepend.rb
734
728
  - lib/solargraph/pin/reference/require.rb
735
729
  - lib/solargraph/pin/reference/superclass.rb
730
+ - lib/solargraph/pin/reference/type_alias.rb
736
731
  - lib/solargraph/pin/search.rb
737
732
  - lib/solargraph/pin/signature.rb
738
733
  - lib/solargraph/pin/singleton.rb
@@ -839,14 +834,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
839
834
  requirements:
840
835
  - - ">="
841
836
  - !ruby/object:Gem::Version
842
- version: '3.0'
837
+ version: '3.1'
843
838
  required_rubygems_version: !ruby/object:Gem::Requirement
844
839
  requirements:
845
840
  - - ">="
846
841
  - !ruby/object:Gem::Version
847
842
  version: '0'
848
843
  requirements: []
849
- rubygems_version: 3.6.7
844
+ rubygems_version: 4.0.6
850
845
  specification_version: 4
851
846
  summary: A Ruby language server
852
847
  test_files: []