solargraph 0.56.2 → 0.58.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 (147) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/linting.yml +127 -0
  3. data/.github/workflows/plugins.yml +183 -7
  4. data/.github/workflows/rspec.yml +55 -5
  5. data/.github/workflows/typecheck.yml +6 -3
  6. data/.gitignore +5 -0
  7. data/.overcommit.yml +72 -0
  8. data/.rspec +1 -0
  9. data/.rubocop.yml +66 -0
  10. data/.rubocop_todo.yml +1279 -0
  11. data/.yardopts +1 -0
  12. data/CHANGELOG.md +69 -0
  13. data/README.md +8 -4
  14. data/Rakefile +125 -13
  15. data/bin/solargraph +8 -5
  16. data/lib/solargraph/api_map/cache.rb +3 -2
  17. data/lib/solargraph/api_map/constants.rb +279 -0
  18. data/lib/solargraph/api_map/index.rb +49 -31
  19. data/lib/solargraph/api_map/source_to_yard.rb +13 -4
  20. data/lib/solargraph/api_map/store.rb +144 -26
  21. data/lib/solargraph/api_map.rb +217 -245
  22. data/lib/solargraph/bench.rb +1 -0
  23. data/lib/solargraph/complex_type/type_methods.rb +6 -0
  24. data/lib/solargraph/complex_type/unique_type.rb +19 -12
  25. data/lib/solargraph/complex_type.rb +24 -3
  26. data/lib/solargraph/convention/active_support_concern.rb +111 -0
  27. data/lib/solargraph/convention/base.rb +17 -0
  28. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +1 -0
  29. data/lib/solargraph/convention/data_definition/data_definition_node.rb +4 -2
  30. data/lib/solargraph/convention/data_definition.rb +2 -1
  31. data/lib/solargraph/convention/gemspec.rb +1 -1
  32. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +1 -0
  33. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +3 -1
  34. data/lib/solargraph/convention/struct_definition.rb +36 -13
  35. data/lib/solargraph/convention.rb +31 -2
  36. data/lib/solargraph/diagnostics/rubocop.rb +6 -1
  37. data/lib/solargraph/diagnostics/rubocop_helpers.rb +5 -3
  38. data/lib/solargraph/doc_map.rb +44 -13
  39. data/lib/solargraph/environ.rb +9 -2
  40. data/lib/solargraph/equality.rb +1 -0
  41. data/lib/solargraph/gem_pins.rb +21 -11
  42. data/lib/solargraph/language_server/host/dispatch.rb +2 -0
  43. data/lib/solargraph/language_server/host/message_worker.rb +3 -0
  44. data/lib/solargraph/language_server/host.rb +12 -5
  45. data/lib/solargraph/language_server/message/base.rb +2 -1
  46. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +1 -1
  47. data/lib/solargraph/language_server/message/text_document/definition.rb +2 -0
  48. data/lib/solargraph/language_server/message/text_document/formatting.rb +19 -2
  49. data/lib/solargraph/language_server/message/text_document/type_definition.rb +1 -0
  50. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +2 -0
  51. data/lib/solargraph/language_server/progress.rb +8 -0
  52. data/lib/solargraph/language_server/request.rb +4 -1
  53. data/lib/solargraph/library.rb +11 -18
  54. data/lib/solargraph/location.rb +3 -0
  55. data/lib/solargraph/logging.rb +11 -2
  56. data/lib/solargraph/page.rb +3 -0
  57. data/lib/solargraph/parser/comment_ripper.rb +8 -1
  58. data/lib/solargraph/parser/flow_sensitive_typing.rb +33 -5
  59. data/lib/solargraph/parser/node_processor/base.rb +1 -1
  60. data/lib/solargraph/parser/node_processor.rb +6 -2
  61. data/lib/solargraph/parser/parser_gem/class_methods.rb +3 -13
  62. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -0
  63. data/lib/solargraph/parser/parser_gem/node_chainer.rb +3 -1
  64. data/lib/solargraph/parser/parser_gem/node_methods.rb +5 -16
  65. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +1 -0
  66. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +3 -2
  67. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +2 -0
  68. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -0
  69. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +64 -8
  70. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +12 -3
  71. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +36 -16
  72. data/lib/solargraph/parser/region.rb +3 -0
  73. data/lib/solargraph/parser/snippet.rb +2 -0
  74. data/lib/solargraph/pin/base.rb +77 -14
  75. data/lib/solargraph/pin/base_variable.rb +6 -5
  76. data/lib/solargraph/pin/block.rb +3 -2
  77. data/lib/solargraph/pin/callable.rb +14 -1
  78. data/lib/solargraph/pin/closure.rb +5 -7
  79. data/lib/solargraph/pin/common.rb +6 -2
  80. data/lib/solargraph/pin/constant.rb +2 -0
  81. data/lib/solargraph/pin/local_variable.rb +1 -2
  82. data/lib/solargraph/pin/method.rb +28 -9
  83. data/lib/solargraph/pin/method_alias.rb +3 -0
  84. data/lib/solargraph/pin/parameter.rb +24 -10
  85. data/lib/solargraph/pin/proxy_type.rb +5 -1
  86. data/lib/solargraph/pin/reference/override.rb +15 -1
  87. data/lib/solargraph/pin/reference/superclass.rb +5 -0
  88. data/lib/solargraph/pin/reference.rb +17 -0
  89. data/lib/solargraph/pin/search.rb +6 -1
  90. data/lib/solargraph/pin/signature.rb +2 -0
  91. data/lib/solargraph/pin/symbol.rb +5 -0
  92. data/lib/solargraph/pin_cache.rb +64 -4
  93. data/lib/solargraph/position.rb +3 -0
  94. data/lib/solargraph/range.rb +5 -0
  95. data/lib/solargraph/rbs_map/conversions.rb +29 -6
  96. data/lib/solargraph/rbs_map/core_fills.rb +18 -0
  97. data/lib/solargraph/rbs_map/core_map.rb +14 -7
  98. data/lib/solargraph/rbs_map.rb +14 -1
  99. data/lib/solargraph/shell.rb +85 -1
  100. data/lib/solargraph/source/chain/call.rb +7 -3
  101. data/lib/solargraph/source/chain/constant.rb +3 -66
  102. data/lib/solargraph/source/chain/if.rb +1 -1
  103. data/lib/solargraph/source/chain/link.rb +11 -2
  104. data/lib/solargraph/source/chain/or.rb +1 -1
  105. data/lib/solargraph/source/chain.rb +11 -2
  106. data/lib/solargraph/source/change.rb +2 -2
  107. data/lib/solargraph/source/cursor.rb +2 -3
  108. data/lib/solargraph/source/source_chainer.rb +1 -1
  109. data/lib/solargraph/source.rb +6 -3
  110. data/lib/solargraph/source_map/clip.rb +18 -26
  111. data/lib/solargraph/source_map/data.rb +4 -0
  112. data/lib/solargraph/source_map/mapper.rb +2 -2
  113. data/lib/solargraph/source_map.rb +28 -16
  114. data/lib/solargraph/type_checker/param_def.rb +2 -0
  115. data/lib/solargraph/type_checker/rules.rb +30 -8
  116. data/lib/solargraph/type_checker.rb +301 -186
  117. data/lib/solargraph/version.rb +1 -1
  118. data/lib/solargraph/workspace/config.rb +21 -5
  119. data/lib/solargraph/workspace/require_paths.rb +97 -0
  120. data/lib/solargraph/workspace.rb +30 -67
  121. data/lib/solargraph/yard_map/mapper/to_method.rb +4 -3
  122. data/lib/solargraph/yard_map/mapper/to_namespace.rb +1 -0
  123. data/lib/solargraph/yard_map/to_method.rb +2 -1
  124. data/lib/solargraph/yardoc.rb +39 -3
  125. data/lib/solargraph.rb +2 -0
  126. data/rbs/fills/bundler/0/bundler.rbs +4271 -0
  127. data/rbs/fills/open3/0/open3.rbs +172 -0
  128. data/rbs/fills/rubygems/0/basic_specification.rbs +326 -0
  129. data/rbs/fills/rubygems/0/errors.rbs +364 -0
  130. data/rbs/fills/rubygems/0/spec_fetcher.rbs +107 -0
  131. data/rbs/fills/rubygems/0/specification.rbs +1753 -0
  132. data/rbs/fills/{tuple.rbs → tuple/tuple.rbs} +2 -3
  133. data/rbs_collection.yaml +4 -4
  134. data/sig/shims/ast/0/node.rbs +5 -0
  135. data/sig/shims/ast/2.4/.rbs_meta.yaml +9 -0
  136. data/sig/shims/ast/2.4/ast.rbs +73 -0
  137. data/sig/shims/parser/3.2.0.1/builders/default.rbs +195 -0
  138. data/sig/shims/parser/3.2.0.1/manifest.yaml +7 -0
  139. data/sig/shims/parser/3.2.0.1/parser.rbs +201 -0
  140. data/sig/shims/parser/3.2.0.1/polyfill.rbs +4 -0
  141. data/sig/shims/thor/1.2.0.1/.rbs_meta.yaml +9 -0
  142. data/sig/shims/thor/1.2.0.1/manifest.yaml +7 -0
  143. data/sig/shims/thor/1.2.0.1/thor.rbs +17 -0
  144. data/solargraph.gemspec +26 -5
  145. metadata +181 -13
  146. data/lib/.rubocop.yml +0 -22
  147. data/lib/solargraph/parser/node_methods.rb +0 -97
@@ -15,15 +15,16 @@ module Solargraph
15
15
  # @return [void]
16
16
  def require_rubocop(version = nil)
17
17
  begin
18
+ # @type [String]
18
19
  gem_path = Gem::Specification.find_by_name('rubocop', version).full_gem_path
19
20
  gem_lib_path = File.join(gem_path, 'lib')
20
21
  $LOAD_PATH.unshift(gem_lib_path) unless $LOAD_PATH.include?(gem_lib_path)
21
- # @todo Gem::MissingSpecVersionError is undocumented for some reason
22
- # @sg-ignore
23
22
  rescue Gem::MissingSpecVersionError => e
23
+ # @type [Array<Gem::Specification>]
24
+ specs = e.specs
24
25
  raise InvalidRubocopVersionError,
25
26
  "could not find '#{e.name}' (#{e.requirement}) - "\
26
- "did find: [#{e.specs.map { |s| s.version.version }.join(', ')}]"
27
+ "did find: [#{specs.map { |s| s.version.version }.join(', ')}]"
27
28
  end
28
29
  require 'rubocop'
29
30
  end
@@ -37,6 +38,7 @@ module Solargraph
37
38
  args = ['-f', 'j', '--force-exclusion', filename]
38
39
  base_options = RuboCop::Options.new
39
40
  options, paths = base_options.parse(args)
41
+ # @sg-ignore
40
42
  options[:stdin] = code
41
43
  [options, paths]
42
44
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'pathname'
4
4
  require 'benchmark'
5
+ require 'open3'
5
6
 
6
7
  module Solargraph
7
8
  # A collection of pins generated from required gems.
@@ -32,8 +33,10 @@ module Solargraph
32
33
  # @return [Array<Gem::Specification>]
33
34
  attr_reader :uncached_rbs_collection_gemspecs
34
35
 
36
+ # @return [String, nil]
35
37
  attr_reader :rbs_collection_path
36
38
 
39
+ # @return [String, nil]
37
40
  attr_reader :rbs_collection_config_path
38
41
 
39
42
  # @return [Workspace, nil]
@@ -52,10 +55,13 @@ module Solargraph
52
55
  @rbs_collection_path = workspace&.rbs_collection_path
53
56
  @rbs_collection_config_path = workspace&.rbs_collection_config_path
54
57
  @environ = Convention.for_global(self)
58
+ @requires.concat @environ.requires if @environ
55
59
  load_serialized_gem_pins
56
60
  pins.concat @environ.pins
57
61
  end
58
62
 
63
+ # @param out [IO]
64
+ # @return [void]
59
65
  def cache_all!(out)
60
66
  # if we log at debug level:
61
67
  if logger.info?
@@ -73,12 +79,18 @@ module Solargraph
73
79
  @uncached_yard_gemspecs = []
74
80
  end
75
81
 
82
+ # @param gemspec [Gem::Specification]
83
+ # @param out [IO]
84
+ # @return [void]
76
85
  def cache_yard_pins(gemspec, out)
77
- pins = GemPins.build_yard_pins(gemspec)
86
+ pins = GemPins.build_yard_pins(yard_plugins, gemspec)
78
87
  PinCache.serialize_yard_gem(gemspec, pins)
79
88
  logger.info { "Cached #{pins.length} YARD pins for gem #{gemspec.name}:#{gemspec.version}" } unless pins.empty?
80
89
  end
81
90
 
91
+ # @param gemspec [Gem::Specification]
92
+ # @param out [IO]
93
+ # @return [void]
82
94
  def cache_rbs_collection_pins(gemspec, out)
83
95
  rbs_map = RbsMap.from_gemspec(gemspec, rbs_collection_path, rbs_collection_config_path)
84
96
  pins = rbs_map.pins
@@ -90,6 +102,9 @@ module Solargraph
90
102
  end
91
103
 
92
104
  # @param gemspec [Gem::Specification]
105
+ # @param rebuild [Boolean] whether to rebuild the pins even if they are cached
106
+ # @param out [IO, nil] output stream for logging
107
+ # @return [void]
93
108
  def cache(gemspec, rebuild: false, out: nil)
94
109
  build_yard = uncached_yard_gemspecs.include?(gemspec) || rebuild
95
110
  build_rbs_collection = uncached_rbs_collection_gemspecs.include?(gemspec) || rebuild
@@ -113,30 +128,42 @@ module Solargraph
113
128
  @unresolved_requires ||= required_gems_map.select { |_, gemspecs| gemspecs.nil? }.keys
114
129
  end
115
130
 
131
+ # @return [Hash{Array(String, String) => Array<Pin::Base>}] Indexed by gemspec name and version
116
132
  def self.all_yard_gems_in_memory
117
133
  @yard_gems_in_memory ||= {}
118
134
  end
119
135
 
136
+ # @return [Hash{String => Hash{Array(String, String) => Array<Pin::Base>}}] stored by RBS collection path
120
137
  def self.all_rbs_collection_gems_in_memory
121
138
  @rbs_collection_gems_in_memory ||= {}
122
139
  end
123
140
 
141
+ # @return [Hash{Array(String, String) => Array<Pin::Base>}] Indexed by gemspec name and version
124
142
  def yard_pins_in_memory
125
143
  self.class.all_yard_gems_in_memory
126
144
  end
127
145
 
146
+ # @return [Hash{Array(String, String) => Array<Pin::Base>}] Indexed by gemspec name and version
128
147
  def rbs_collection_pins_in_memory
129
148
  self.class.all_rbs_collection_gems_in_memory[rbs_collection_path] ||= {}
130
149
  end
131
150
 
151
+ # @return [Hash{Array(String, String) => Array<Pin::Base>}] Indexed by gemspec name and version
132
152
  def self.all_combined_pins_in_memory
133
153
  @combined_pins_in_memory ||= {}
134
154
  end
135
155
 
156
+ # @todo this should also include an index by the hash of the RBS collection
157
+ # @return [Hash{Array(String, String) => Array<Pin::Base>}] Indexed by gemspec name and version
136
158
  def combined_pins_in_memory
137
159
  self.class.all_combined_pins_in_memory
138
160
  end
139
161
 
162
+ # @return [Array<String>]
163
+ def yard_plugins
164
+ @environ.yard_plugins
165
+ end
166
+
140
167
  # @return [Set<Gem::Specification>]
141
168
  def dependencies
142
169
  @dependencies ||= (gemspecs.flat_map { |spec| fetch_dependencies(spec) } - gemspecs).to_set
@@ -150,7 +177,11 @@ module Solargraph
150
177
  @uncached_yard_gemspecs = []
151
178
  @uncached_rbs_collection_gemspecs = []
152
179
  with_gemspecs, without_gemspecs = required_gems_map.partition { |_, v| v }
180
+ # @sg-ignore Need support for RBS duck interfaces like _ToHash
181
+ # @type [Array<String>]
153
182
  paths = Hash[without_gemspecs].keys
183
+ # @sg-ignore Need support for RBS duck interfaces like _ToHash
184
+ # @type [Array<Gem::Specification>]
154
185
  gemspecs = Hash[with_gemspecs].values.flatten.compact + dependencies.to_a
155
186
 
156
187
  paths.each do |path|
@@ -181,7 +212,7 @@ module Solargraph
181
212
  end
182
213
 
183
214
  # @param gemspec [Gem::Specification]
184
- # @return [Array<Pin::Base>]
215
+ # @return [Array<Pin::Base>, nil]
185
216
  def deserialize_yard_pin_cache gemspec
186
217
  if yard_pins_in_memory.key?([gemspec.name, gemspec.version])
187
218
  return yard_pins_in_memory[[gemspec.name, gemspec.version]]
@@ -259,6 +290,8 @@ module Solargraph
259
290
  end
260
291
  end
261
292
 
293
+ # @param gemspec [Gem::Specification]
294
+ # @param rbs_version_cache_key [String]
262
295
  # @return [Array<Pin::Base>, nil]
263
296
  def deserialize_rbs_collection_cache gemspec, rbs_version_cache_key
264
297
  return if rbs_collection_pins_in_memory.key?([gemspec, rbs_version_cache_key])
@@ -274,22 +307,13 @@ module Solargraph
274
307
  end
275
308
  end
276
309
 
277
- # @param gemspec [Gem::Specification]
278
- # @return [Boolean]
279
- def try_gem_in_memory gemspec
280
- gempins = DocMap.gems_in_memory[gemspec]
281
- return false unless gempins
282
- Solargraph.logger.debug "Found #{gemspec.name} #{gemspec.version} in memory"
283
- @pins.concat gempins
284
- true
285
- end
286
-
287
310
  # @param path [String]
288
311
  # @return [::Array<Gem::Specification>, nil]
289
312
  def resolve_path_to_gemspecs path
290
313
  return nil if path.empty?
291
314
  return gemspecs_required_from_bundler if path == 'bundler/require'
292
315
 
316
+ # @type [Gem::Specification, nil]
293
317
  gemspec = Gem::Specification.find_by_path(path)
294
318
  if gemspec.nil?
295
319
  gem_name_guess = path.split('/').first
@@ -313,10 +337,12 @@ module Solargraph
313
337
  # @param gemspec [Gem::Specification]
314
338
  # @return [Gem::Specification]
315
339
  def gemspec_or_preference gemspec
340
+ # :nocov: dormant feature
316
341
  return gemspec unless preference_map.key?(gemspec.name)
317
342
  return gemspec if gemspec.version == preference_map[gemspec.name].version
318
343
 
319
- change_gemspec_version gemspec, preference_map[by_path.name].version
344
+ change_gemspec_version gemspec, preference_map[gemspec.name].version
345
+ # :nocov:
320
346
  end
321
347
 
322
348
  # @param gemspec [Gem::Specification]
@@ -333,13 +359,16 @@ module Solargraph
333
359
  # @return [Array<Gem::Specification>]
334
360
  def fetch_dependencies gemspec
335
361
  # @param spec [Gem::Dependency]
362
+ # @param deps [Set<Gem::Specification>]
336
363
  only_runtime_dependencies(gemspec).each_with_object(Set.new) do |spec, deps|
337
364
  Solargraph.logger.info "Adding #{spec.name} dependency for #{gemspec.name}"
338
365
  dep = Gem.loaded_specs[spec.name]
339
366
  # @todo is next line necessary?
367
+ # @sg-ignore Unresolved call to requirement on Gem::Dependency
340
368
  dep ||= Gem::Specification.find_by_name(spec.name, spec.requirement)
341
369
  deps.merge fetch_dependencies(dep) if deps.add?(dep)
342
370
  rescue Gem::MissingSpecError
371
+ # @sg-ignore Unresolved call to requirement on Gem::Dependency
343
372
  Solargraph.logger.warn "Gem dependency #{spec.name} #{spec.requirement} for #{gemspec.name} not found in RubyGems."
344
373
  end.to_a
345
374
  end
@@ -355,6 +384,7 @@ module Solargraph
355
384
  self.class.inspect
356
385
  end
357
386
 
387
+ # @return [Array<Gem::Specification>, nil]
358
388
  def gemspecs_required_from_bundler
359
389
  # @todo Handle projects with custom Bundler/Gemfile setups
360
390
  return unless workspace.gemfile?
@@ -377,6 +407,7 @@ module Solargraph
377
407
  end
378
408
  end
379
409
 
410
+ # @return [Array<Gem::Specification>, nil]
380
411
  def gemspecs_required_from_external_bundle
381
412
  logger.info 'Fetching gemspecs required from external bundle'
382
413
  return [] unless workspace&.directory
@@ -13,16 +13,21 @@ module Solargraph
13
13
  # @return [Array<String>]
14
14
  attr_reader :domains
15
15
 
16
- # @return [Array<Pin::Reference::Override>]
16
+ # @return [Array<Pin::Base>]
17
17
  attr_reader :pins
18
18
 
19
+ # @return [Array<String>]
20
+ attr_reader :yard_plugins
21
+
19
22
  # @param requires [Array<String>]
20
23
  # @param domains [Array<String>]
21
24
  # @param pins [Array<Pin::Base>]
22
- def initialize requires: [], domains: [], pins: []
25
+ # @param yard_plugins [Array<String>]
26
+ def initialize requires: [], domains: [], pins: [], yard_plugins: []
23
27
  @requires = requires
24
28
  @domains = domains
25
29
  @pins = pins
30
+ @yard_plugins = yard_plugins
26
31
  end
27
32
 
28
33
  # @return [self]
@@ -30,6 +35,7 @@ module Solargraph
30
35
  domains.clear
31
36
  requires.clear
32
37
  pins.clear
38
+ yard_plugins.clear
33
39
  self
34
40
  end
35
41
 
@@ -39,6 +45,7 @@ module Solargraph
39
45
  domains.concat other.domains
40
46
  requires.concat other.requires
41
47
  pins.concat other.pins
48
+ yard_plugins.concat other.yard_plugins
42
49
  self
43
50
  end
44
51
  end
@@ -12,6 +12,7 @@ module Solargraph
12
12
  # @return [Boolean]
13
13
  def eql?(other)
14
14
  self.class.eql?(other.class) &&
15
+ # @sg-ignore https://github.com/castwide/solargraph/pull/1114
15
16
  equality_fields.eql?(other.equality_fields)
16
17
  end
17
18
 
@@ -11,17 +11,9 @@ module Solargraph
11
11
  include Logging
12
12
  end
13
13
 
14
- # @param gemspec [Gem::Specification]
15
- # @return [Array<Pin::Base>]
16
- def self.build_yard_pins(gemspec)
17
- Yardoc.cache(gemspec) unless Yardoc.cached?(gemspec)
18
- yardoc = Yardoc.load!(gemspec)
19
- YardMap::Mapper.new(yardoc, gemspec).map
20
- end
21
-
22
14
  # @param pins [Array<Pin::Base>]
15
+ # @return [Array<Pin::Base>]
23
16
  def self.combine_method_pins_by_path(pins)
24
- # bad_pins = pins.select { |pin| pin.is_a?(Pin::Method) && pin.path == 'StringIO.open' && pin.source == :rbs }; raise "wtf: #{bad_pins}" if bad_pins.length > 1
25
17
  method_pins, alias_pins = pins.partition { |pin| pin.class == Pin::Method }
26
18
  by_path = method_pins.group_by(&:path)
27
19
  by_path.transform_values! do |pins|
@@ -30,8 +22,14 @@ module Solargraph
30
22
  by_path.values + alias_pins
31
23
  end
32
24
 
25
+ # @param pins [Array<Pin::Method>]
26
+ # @return [Pin::Method, nil]
33
27
  def self.combine_method_pins(*pins)
34
- out = pins.reduce(nil) do |memo, pin|
28
+ # @type [Pin::Method, nil]
29
+ combined_pin = nil
30
+ # @param memo [Pin::Method, nil]
31
+ # @param pin [Pin::Method]
32
+ out = pins.reduce(combined_pin) do |memo, pin|
35
33
  next pin if memo.nil?
36
34
  if memo == pin && memo.source != :combined
37
35
  # @todo we should track down situations where we are handled
@@ -45,8 +43,19 @@ module Solargraph
45
43
  out
46
44
  end
47
45
 
46
+ # @param yard_plugins [Array<String>] The names of YARD plugins to use.
47
+ # @param gemspec [Gem::Specification]
48
+ # @return [Array<Pin::Base>]
49
+ def self.build_yard_pins(yard_plugins, gemspec)
50
+ Yardoc.cache(yard_plugins, gemspec) unless Yardoc.cached?(gemspec)
51
+ return [] unless Yardoc.cached?(gemspec)
52
+ yardoc = Yardoc.load!(gemspec)
53
+ YardMap::Mapper.new(yardoc, gemspec).map
54
+ end
55
+
48
56
  # @param yard_pins [Array<Pin::Base>]
49
- # @param rbs_map [RbsMap]
57
+ # @param rbs_pins [Array<Pin::Base>]
58
+ #
50
59
  # @return [Array<Pin::Base>]
51
60
  def self.combine(yard_pins, rbs_pins)
52
61
  in_yard = Set.new
@@ -57,6 +66,7 @@ module Solargraph
57
66
  next yard_pin unless rbs_pin && yard_pin.class == Pin::Method
58
67
 
59
68
  unless rbs_pin
69
+ # @sg-ignore https://github.com/castwide/solargraph/pull/1114
60
70
  logger.debug { "GemPins.combine: No rbs pin for #{yard_pin.path} - using YARD's '#{yard_pin.inspect} (return_type=#{yard_pin.return_type}; signatures=#{yard_pin.signatures})" }
61
71
  next yard_pin
62
72
  end
@@ -95,6 +95,7 @@ module Solargraph
95
95
  nil
96
96
  end
97
97
 
98
+ # @return [Hash{String => undefined}]
98
99
  def options
99
100
  @options ||= {}.freeze
100
101
  end
@@ -118,6 +119,7 @@ module Solargraph
118
119
  end
119
120
 
120
121
  # @param library [Solargraph::Library]
122
+ # @param progress [Solargraph::LanguageServer::Progress, nil]
121
123
  # @return [void]
122
124
  def update progress
123
125
  progress&.send(self)
@@ -72,10 +72,12 @@ module Solargraph
72
72
 
73
73
  private
74
74
 
75
+ # @return [Hash, nil]
75
76
  def next_message
76
77
  cancel_message || next_priority
77
78
  end
78
79
 
80
+ # @return [Hash, nil]
79
81
  def cancel_message
80
82
  # Handle cancellations first
81
83
  idx = messages.find_index { |msg| msg['method'] == '$/cancelRequest' }
@@ -86,6 +88,7 @@ module Solargraph
86
88
  msg
87
89
  end
88
90
 
91
+ # @return [Hash, nil]
89
92
  def next_priority
90
93
  # Prioritize updates and version-dependent messages for performance
91
94
  idx = messages.find_index do |msg|
@@ -94,7 +94,8 @@ module Solargraph
94
94
  # processed, caller is responsible for sending the response.
95
95
  #
96
96
  # @param request [Hash{String => unspecified}] The contents of the message.
97
- # @return [Solargraph::LanguageServer::Message::Base, nil] The message handler.
97
+ #
98
+ # @return [Solargraph::LanguageServer::Message::Base, Solargraph::LanguageServer::Request, nil] The message handler.
98
99
  def receive request
99
100
  if request['method']
100
101
  logger.info "Host received ##{request['id']} #{request['method']}"
@@ -299,6 +300,7 @@ module Solargraph
299
300
  end
300
301
  end
301
302
 
303
+ # @return [String]
302
304
  def command_path
303
305
  options['commandPath'] || 'solargraph'
304
306
  end
@@ -502,6 +504,7 @@ module Solargraph
502
504
  name: 'new',
503
505
  scope: :class,
504
506
  location: pin.location,
507
+ # @sg-ignore Unresolved call to parameters on Solargraph::Pin::Base
505
508
  parameters: pin.parameters,
506
509
  return_type: ComplexType.try_parse(params['data']['path']),
507
510
  comments: pin.comments,
@@ -533,7 +536,7 @@ module Solargraph
533
536
  # @param uri [String]
534
537
  # @param line [Integer]
535
538
  # @param column [Integer]
536
- # @return [Solargraph::SourceMap::Completion]
539
+ # @return [Solargraph::SourceMap::Completion, nil]
537
540
  def completions_at uri, line, column
538
541
  library = library_for(uri)
539
542
  library.completions_at uri_to_file(uri), line, column
@@ -547,7 +550,7 @@ module Solargraph
547
550
  # @param uri [String]
548
551
  # @param line [Integer]
549
552
  # @param column [Integer]
550
- # @return [Array<Solargraph::Pin::Base>]
553
+ # @return [Array<Solargraph::Pin::Base>, nil]
551
554
  def definitions_at uri, line, column
552
555
  library = library_for(uri)
553
556
  library.definitions_at(uri_to_file(uri), line, column)
@@ -556,7 +559,7 @@ module Solargraph
556
559
  # @param uri [String]
557
560
  # @param line [Integer]
558
561
  # @param column [Integer]
559
- # @return [Array<Solargraph::Pin::Base>]
562
+ # @return [Array<Solargraph::Pin::Base>, nil]
560
563
  def type_definitions_at uri, line, column
561
564
  library = library_for(uri)
562
565
  library.type_definitions_at(uri_to_file(uri), line, column)
@@ -580,6 +583,10 @@ module Solargraph
580
583
  def references_from uri, line, column, strip: true, only: false
581
584
  library = library_for(uri)
582
585
  library.references_from(uri_to_file(uri), line, column, strip: strip, only: only)
586
+ rescue FileNotFoundError, InvalidOffsetError => e
587
+ Solargraph.logger.warn "[#{e.class}] #{e.message}"
588
+ Solargraph.logger.debug e.backtrace
589
+ []
583
590
  end
584
591
 
585
592
  # @param query [String]
@@ -716,7 +723,7 @@ module Solargraph
716
723
  # A hash of client requests by ID. The host uses this to keep track of
717
724
  # pending responses.
718
725
  #
719
- # @return [Hash{Integer => Solargraph::LanguageServer::Host}]
726
+ # @return [Hash{Integer => Solargraph::LanguageServer::Request}]
720
727
  def requests
721
728
  @requests ||= {}
722
729
  end
@@ -16,7 +16,7 @@ module Solargraph
16
16
  # @return [String]
17
17
  attr_reader :method
18
18
 
19
- # @return [Hash{String => Array<undefined>, Hash{String => undefined}, String, Integer}]
19
+ # @return [Hash{String => undefined}]
20
20
  attr_reader :params
21
21
 
22
22
  # @return [Hash, Array, nil]
@@ -79,6 +79,7 @@ module Solargraph
79
79
 
80
80
  private
81
81
 
82
+ # @return [void]
82
83
  def accept_or_cancel
83
84
  if host.cancel?(id)
84
85
  # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#cancelRequest
@@ -83,7 +83,7 @@ module Solargraph
83
83
  @fetched = true
84
84
  begin
85
85
  @available ||= begin
86
- # @sg-ignore
86
+ # @sg-ignore Variable type could not be inferred for tuple
87
87
  # @type [Gem::Dependency, nil]
88
88
  tuple = CheckGemVersion.fetcher.search_for_dependency(Gem::Dependency.new('solargraph')).flatten.first
89
89
  if tuple.nil?
@@ -10,6 +10,7 @@ module Solargraph::LanguageServer::Message::TextDocument
10
10
 
11
11
  private
12
12
 
13
+ # @return [Array<Hash>, nil]
13
14
  def code_location
14
15
  suggestions = host.definitions_at(params['textDocument']['uri'], @line, @column)
15
16
  return nil if suggestions.empty?
@@ -21,6 +22,7 @@ module Solargraph::LanguageServer::Message::TextDocument
21
22
  end
22
23
  end
23
24
 
25
+ # @return [Array<Hash>, nil]
24
26
  def require_location
25
27
  # @todo Terrible hack
26
28
  lib = host.library_for(params['textDocument']['uri'])
@@ -18,10 +18,18 @@ module Solargraph
18
18
 
19
19
  require_rubocop(config['version'])
20
20
  options, paths = ::RuboCop::Options.new.parse(args)
21
+ # @sg-ignore Unresolved call to []=
21
22
  options[:stdin] = original
22
- corrections = redirect_stdout do
23
- ::RuboCop::Runner.new(options, ::RuboCop::ConfigStore.new).run(paths)
23
+
24
+ # Ensure only one instance of RuboCop::Runner is running at
25
+ # a time - it uses 'chdir' to read config files with ERB,
26
+ # which can conflict with other chdirs.
27
+ corrections = Solargraph::CHDIR_MUTEX.synchronize do
28
+ redirect_stdout do
29
+ ::RuboCop::Runner.new(options, ::RuboCop::ConfigStore.new).run(paths)
30
+ end
24
31
  end
32
+ # @sg-ignore Unresolved call to []=
25
33
  result = options[:stdin]
26
34
 
27
35
  log_corrections(corrections)
@@ -34,6 +42,7 @@ module Solargraph
34
42
  private
35
43
 
36
44
  # @param corrections [String]
45
+ # @return [void]
37
46
  def log_corrections(corrections)
38
47
  corrections = corrections&.strip
39
48
  return if corrections&.empty?
@@ -45,6 +54,8 @@ module Solargraph
45
54
  end
46
55
  end
47
56
 
57
+ # @param file_uri [String]
58
+ # @return [Hash{String => undefined}]
48
59
  def config_for(file_uri)
49
60
  conf = host.formatter_config(file_uri)
50
61
  return {} unless conf.is_a?(Hash)
@@ -52,7 +63,9 @@ module Solargraph
52
63
  conf['rubocop'] || {}
53
64
  end
54
65
 
66
+ # @param file_uri [String]
55
67
  # @param config [Hash{String => String}]
68
+ # @return [Array<String>]
56
69
  def cli_args file_uri, config
57
70
  file = UriHelpers.uri_to_file(file_uri)
58
71
  args = [
@@ -71,6 +84,8 @@ module Solargraph
71
84
  end
72
85
 
73
86
  # @param config [Hash{String => String}]
87
+ # @sg-ignore
88
+ # @return [Class<RuboCop::Formatter::BaseFormatter>]
74
89
  def formatter_class(config)
75
90
  if self.class.const_defined?('BlankRubocopFormatter')
76
91
  # @sg-ignore
@@ -83,7 +98,9 @@ module Solargraph
83
98
  end
84
99
 
85
100
  # @param value [Array, String]
101
+ # @return [String, nil]
86
102
  def cop_list(value)
103
+ # @type [String]
87
104
  value = value.join(',') if value.respond_to?(:join)
88
105
  return nil if value == '' || !value.is_a?(String)
89
106
  value
@@ -10,6 +10,7 @@ module Solargraph::LanguageServer::Message::TextDocument
10
10
 
11
11
  private
12
12
 
13
+ # @return [Array<Hash>, nil]
13
14
  def code_location
14
15
  suggestions = host.type_definitions_at(params['textDocument']['uri'], @line, @column)
15
16
  return nil if suggestions.empty?
@@ -9,11 +9,13 @@ module Solargraph::LanguageServer::Message::Workspace
9
9
 
10
10
  private
11
11
 
12
+ # @return [void]
12
13
  def add_folders
13
14
  return unless params['event'] && params['event']['added']
14
15
  host.prepare_folders params['event']['added']
15
16
  end
16
17
 
18
+ # @return [void]
17
19
  def remove_folders
18
20
  return unless params['event'] && params['event']['removed']
19
21
  params['event']['removed'].each do |folder|
@@ -39,6 +39,7 @@ module Solargraph
39
39
 
40
40
  # @param message [String]
41
41
  # @param percentage [Integer]
42
+ # @return [void]
42
43
  def begin message, percentage
43
44
  @kind = 'begin'
44
45
  @message = message
@@ -47,6 +48,7 @@ module Solargraph
47
48
 
48
49
  # @param message [String]
49
50
  # @param percentage [Integer]
51
+ # @return [void]
50
52
  def report message, percentage
51
53
  @kind = 'report'
52
54
  @message = message
@@ -54,6 +56,7 @@ module Solargraph
54
56
  end
55
57
 
56
58
  # @param message [String]
59
+ # @return [void]
57
60
  def finish message
58
61
  @kind = 'end'
59
62
  @message = message
@@ -62,6 +65,7 @@ module Solargraph
62
65
  end
63
66
 
64
67
  # @param host [Solargraph::LanguageServer::Host]
68
+ # @return [void]
65
69
  def send host
66
70
  return unless host.client_supports_progress? && !finished?
67
71
 
@@ -91,6 +95,7 @@ module Solargraph
91
95
  @status = CREATED
92
96
  end
93
97
 
98
+ # @return [Hash]
94
99
  def build
95
100
  {
96
101
  token: uuid,
@@ -101,6 +106,7 @@ module Solargraph
101
106
  }
102
107
  end
103
108
 
109
+ # @return [Hash]
104
110
  def build_value
105
111
  case kind
106
112
  when 'begin'
@@ -115,6 +121,7 @@ module Solargraph
115
121
  end
116
122
 
117
123
  # @param host [Host]
124
+ # @return [void]
118
125
  def keep_alive host
119
126
  mutex.synchronize { @last = Time.now }
120
127
  @keep_alive ||= Thread.new do
@@ -127,6 +134,7 @@ module Solargraph
127
134
  end
128
135
  end
129
136
 
137
+ # @return [Thread::Mutex]
130
138
  def mutex
131
139
  @mutex ||= Mutex.new
132
140
  end
@@ -11,11 +11,14 @@ module Solargraph
11
11
  end
12
12
 
13
13
  # @param result [Object]
14
- # @return [void]
14
+ # @generic T
15
+ # @yieldreturn [generic<T>]
16
+ # @return [generic<T>, nil]
15
17
  def process result
16
18
  @block.call(result) unless @block.nil?
17
19
  end
18
20
 
21
+ # @return [void]
19
22
  def send_response
20
23
  # noop
21
24
  end