solargraph 0.39.3 → 0.39.8

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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/lib/.rubocop.yml +21 -0
  3. data/lib/solargraph.rb +3 -0
  4. data/lib/solargraph/api_map.rb +27 -21
  5. data/lib/solargraph/api_map/cache.rb +4 -0
  6. data/lib/solargraph/api_map/store.rb +35 -47
  7. data/lib/solargraph/compat.rb +9 -0
  8. data/lib/solargraph/diagnostics/rubocop.rb +2 -1
  9. data/lib/solargraph/diagnostics/rubocop_helpers.rb +4 -1
  10. data/lib/solargraph/documentor.rb +2 -0
  11. data/lib/solargraph/language_server/host.rb +1 -1
  12. data/lib/solargraph/language_server/message/text_document/formatting.rb +6 -2
  13. data/lib/solargraph/language_server/uri_helpers.rb +23 -3
  14. data/lib/solargraph/parser/legacy/node_processors/send_node.rb +10 -0
  15. data/lib/solargraph/parser/rubyvm/node_methods.rb +1 -0
  16. data/lib/solargraph/parser/rubyvm/node_processors.rb +1 -0
  17. data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +6 -1
  18. data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +6 -1
  19. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +13 -40
  20. data/lib/solargraph/pin/attribute.rb +1 -1
  21. data/lib/solargraph/pin/base.rb +2 -2
  22. data/lib/solargraph/pin/base_method.rb +1 -1
  23. data/lib/solargraph/pin/base_variable.rb +1 -1
  24. data/lib/solargraph/pin/block.rb +28 -14
  25. data/lib/solargraph/pin/closure.rb +1 -1
  26. data/lib/solargraph/pin/constant.rb +1 -1
  27. data/lib/solargraph/pin/local_variable.rb +1 -1
  28. data/lib/solargraph/pin/method.rb +1 -1
  29. data/lib/solargraph/pin/method_alias.rb +1 -1
  30. data/lib/solargraph/pin/namespace.rb +1 -1
  31. data/lib/solargraph/pin/parameter.rb +2 -2
  32. data/lib/solargraph/pin/proxy_type.rb +1 -1
  33. data/lib/solargraph/shell.rb +1 -1
  34. data/lib/solargraph/source.rb +14 -3
  35. data/lib/solargraph/source/chain.rb +0 -31
  36. data/lib/solargraph/source/source_chainer.rb +2 -1
  37. data/lib/solargraph/source_map.rb +15 -1
  38. data/lib/solargraph/source_map/mapper.rb +4 -2
  39. data/lib/solargraph/stdlib_fills.rb +8 -0
  40. data/lib/solargraph/type_checker.rb +2 -3
  41. data/lib/solargraph/version.rb +1 -1
  42. data/lib/solargraph/views/_name_type_tag.erb +1 -1
  43. data/lib/solargraph/workspace.rb +1 -1
  44. data/lib/solargraph/yard_map.rb +23 -1
  45. data/lib/solargraph/yard_map/mapper.rb +3 -0
  46. data/lib/solargraph/yard_map/rdoc_to_yard.rb +13 -6
  47. data/solargraph.gemspec +1 -1
  48. data/yardoc/2.2.2.tar.gz +0 -0
  49. metadata +10 -9
  50. data/.rubocop.yml +0 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7445b5b059ff10d5ff6b998209d3988a4d9f20b48b0b3e51b8e6b63000f18d1b
4
- data.tar.gz: d17e09c8fecf38bb4bff9ca4d6985c898a2256cc6c56e4c54599b4be907e27b9
3
+ metadata.gz: 17711680892b43f0ee8848707305dfdb801e7fc15f65e3426fab759dc0309c20
4
+ data.tar.gz: 6e8a9089d203ef9a405da33e449f3c4291d57d741e0bde5d615ecc629276a60a
5
5
  SHA512:
6
- metadata.gz: 61ed8f3f9f68ce49f2496e5fe07eeefbc1121350c15827bc0d600a2417e041d4f2b5d89c861c2f3b4873c20e02bd8fa708d2697b3e73d8e0ee0c858cb7c0f090
7
- data.tar.gz: 6c3646376224f2237e404e4c6fcea9eaf02eaa1cfedebf9a01b6f89896d6454c03b7cbbdc16255549b528243d4c7f73a491f7d94e2d5866c6d15bc18a6db0323
6
+ metadata.gz: 33685a93c52c6417d88f07a76dd4af8c77bf6446d551615e3a745462c622a7808b200638d0af8dbe269cd41c92cac6ba234bb86c29bf7f385ff9d39dd1155ff7
7
+ data.tar.gz: a53bfd06eb1d3e56564ca03b434ba48169e2f56e7712d7eda0f26f67a3830741a70729df280cc80414d69e6586034cbdb7eea11bf31ee87a83a1eabe3b04da05
@@ -0,0 +1,21 @@
1
+ Layout/EndOfLine:
2
+ EnforcedStyle: lf
3
+ Style/MethodDefParentheses:
4
+ Enabled: false
5
+ Layout/EmptyLineAfterGuardClause:
6
+ Enabled: false
7
+ Layout/SpaceAroundMethodCallOperator:
8
+ Enabled: true
9
+ Lint/RaiseException:
10
+ Enabled: true
11
+ Lint/StructNewOverride:
12
+ Enabled: true
13
+ Style/ExponentialNotation:
14
+ Enabled: true
15
+ Style/HashEachMethods:
16
+ Enabled: true
17
+ Style/HashTransformKeys:
18
+ Enabled: true
19
+ Style/HashTransformValues:
20
+ Enabled: true
21
+
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ Encoding.default_external = 'UTF-8'
4
+
5
+ require 'solargraph/compat'
3
6
  require 'solargraph/version'
4
7
 
5
8
  # The top-level namespace for the Solargraph code mapping, documentation,
@@ -26,7 +26,6 @@ module Solargraph
26
26
  def initialize pins: []
27
27
  @source_map_hash = {}
28
28
  @cache = Cache.new
29
- @mutex = Mutex.new
30
29
  @method_alias_stack = []
31
30
  index pins
32
31
  end
@@ -34,13 +33,11 @@ module Solargraph
34
33
  # @param pins [Array<Pin::Base>]
35
34
  # @return [self]
36
35
  def index pins
37
- @mutex.synchronize {
38
- @source_map_hash.clear
39
- @cache.clear
40
- @store = Store.new(pins + YardMap.new.pins)
41
- @unresolved_requires = []
42
- workspace_filenames.clear
43
- }
36
+ @source_map_hash.clear
37
+ @cache.clear
38
+ @store = Store.new(pins + YardMap.new.pins)
39
+ @unresolved_requires = []
40
+ workspace_filenames.clear
44
41
  self
45
42
  end
46
43
 
@@ -123,14 +120,14 @@ module Solargraph
123
120
  reqs.merge br.keys
124
121
  yard_map.change(reqs.to_a, br, bundle.workspace.gemnames)
125
122
  new_store = Store.new(pins + yard_map.pins)
126
- @mutex.synchronize {
127
- @cache.clear
128
- @source_map_hash = new_map_hash
129
- @store = new_store
130
- @unresolved_requires = yard_map.unresolved_requires
131
- workspace_filenames.clear
132
- workspace_filenames.concat bundle.workspace.filenames
133
- }
123
+ @cache.clear
124
+ @source_map_hash = new_map_hash
125
+ @store = new_store
126
+ @unresolved_requires = yard_map.unresolved_requires
127
+ workspace_filenames.clear
128
+ workspace_filenames.concat bundle.workspace.filenames
129
+ @rebindable_method_names = nil
130
+ store.block_pins.each { |blk| blk.rebind(self) }
134
131
  self
135
132
  end
136
133
 
@@ -179,6 +176,16 @@ module Solargraph
179
176
  store.pins
180
177
  end
181
178
 
179
+ def rebindable_method_names
180
+ @rebindable_method_names ||= begin
181
+ result = yard_map.rebindable_method_names
182
+ source_maps.each do |map|
183
+ result.merge map.rebindable_method_names
184
+ end
185
+ result
186
+ end
187
+ end
188
+
182
189
  # An array of pins based on Ruby keywords (`if`, `end`, etc.).
183
190
  #
184
191
  # @return [Array<Solargraph::Pin::Keyword>]
@@ -280,8 +287,7 @@ module Solargraph
280
287
 
281
288
  # @return [Array<Solargraph::Pin::GlobalVariable>]
282
289
  def get_global_variable_pins
283
- # @todo Slow version
284
- pins.select{ |p| p.is_a?(Pin::GlobalVariable) }
290
+ store.pins_by_class(Pin::GlobalVariable)
285
291
  end
286
292
 
287
293
  # Get an array of methods available in a particular context.
@@ -535,17 +541,17 @@ module Solargraph
535
541
  #
536
542
  # @return [Hash{String => SourceMap}]
537
543
  def source_map_hash
538
- @mutex.synchronize { @source_map_hash }
544
+ @source_map_hash
539
545
  end
540
546
 
541
547
  # @return [ApiMap::Store]
542
548
  def store
543
- @mutex.synchronize { @store }
549
+ @store
544
550
  end
545
551
 
546
552
  # @return [Solargraph::ApiMap::Cache]
547
553
  def cache
548
- @mutex.synchronize { @cache }
554
+ @cache
549
555
  end
550
556
 
551
557
  # @param fqns [String] A fully qualified namespace
@@ -10,6 +10,7 @@ module Solargraph
10
10
  @receiver_definitions = {}
11
11
  end
12
12
 
13
+ # @return [Array<Pin::BaseMethod>]
13
14
  def get_methods fqns, scope, visibility, deep
14
15
  @methods[[fqns, scope, visibility.sort, deep]]
15
16
  end
@@ -18,6 +19,7 @@ module Solargraph
18
19
  @methods[[fqns, scope, visibility.sort, deep]] = value
19
20
  end
20
21
 
22
+ # @return [Array<Pin::Base>]
21
23
  def get_constants namespace, context
22
24
  @constants[[namespace, context]]
23
25
  end
@@ -26,6 +28,7 @@ module Solargraph
26
28
  @constants[[namespace, context]] = value
27
29
  end
28
30
 
31
+ # @return [String]
29
32
  def get_qualified_namespace name, context
30
33
  @qualified_namespaces[[name, context]]
31
34
  end
@@ -38,6 +41,7 @@ module Solargraph
38
41
  @receiver_definitions.key? path
39
42
  end
40
43
 
44
+ # @return [Pin::BaseMethod]
41
45
  def get_receiver_definition path
42
46
  @receiver_definitions[path]
43
47
  end
@@ -99,12 +99,12 @@ module Solargraph
99
99
 
100
100
  # @return [Array<Solargraph::Pin::Base>]
101
101
  def namespace_pins
102
- @namespace_pins ||= []
102
+ pins_by_class(Solargraph::Pin::Namespace)
103
103
  end
104
104
 
105
- # @return [Array<Solargraph::Pin::Base>]
105
+ # @return [Array<Solargraph::Pin::BaseMethod>]
106
106
  def method_pins
107
- @method_pins ||= []
107
+ pins_by_class(Solargraph::Pin::BaseMethod)
108
108
  end
109
109
 
110
110
  # @param fqns [String]
@@ -133,7 +133,7 @@ module Solargraph
133
133
 
134
134
  # @return [Array<Pin::Block>]
135
135
  def block_pins
136
- @block_pins ||= []
136
+ pins_by_class(Pin::Block)
137
137
  end
138
138
 
139
139
  def inspect
@@ -141,6 +141,12 @@ module Solargraph
141
141
  to_s
142
142
  end
143
143
 
144
+ # @param klass [Class]
145
+ # @return [Array<Solargraph::Pin::Base>]
146
+ def pins_by_class klass
147
+ @pin_select_cache[klass] ||= @pin_class_hash.select { |key, _| key <= klass }.values.flatten
148
+ end
149
+
144
150
  private
145
151
 
146
152
  # @param fqns [String]
@@ -167,7 +173,7 @@ module Solargraph
167
173
 
168
174
  # @return [Array<Solargraph::Pin::Symbol>]
169
175
  def symbols
170
- @symbols ||= []
176
+ pins_by_class(Pin::Symbol)
171
177
  end
172
178
 
173
179
  def superclass_references
@@ -198,7 +204,7 @@ module Solargraph
198
204
  end
199
205
 
200
206
  def all_instance_variables
201
- @all_instance_variables ||= []
207
+ pins_by_class(Pin::InstanceVariable)
202
208
  end
203
209
 
204
210
  def path_pin_hash
@@ -207,48 +213,29 @@ module Solargraph
207
213
 
208
214
  # @return [void]
209
215
  def index
210
- namespace_map.clear
211
- namespaces.clear
212
- namespace_pins.clear
213
- method_pins.clear
214
- symbols.clear
215
- block_pins.clear
216
- all_instance_variables.clear
217
- path_pin_hash.clear
218
- namespace_map[''] = []
219
- override_pins = []
220
- pins.each do |pin|
221
- namespace_map[pin.namespace] ||= []
222
- namespace_map[pin.namespace].push pin
223
- namespaces.add pin.path if pin.is_a?(Pin::Namespace) && !pin.path.empty?
224
- namespace_pins.push pin if pin.is_a?(Pin::Namespace)
225
- method_pins.push pin if pin.is_a?(Pin::BaseMethod)
226
- symbols.push pin if pin.is_a?(Pin::Symbol)
227
- if pin.is_a?(Pin::Reference::Include)
228
- include_references[pin.namespace] ||= []
229
- include_references[pin.namespace].push pin.name
230
- elsif pin.is_a?(Pin::Reference::Prepend)
231
- prepend_references[pin.namespace] ||= []
232
- prepend_references[pin.namespace].push pin.name
233
- elsif pin.is_a?(Pin::Reference::Extend)
234
- extend_references[pin.namespace] ||= []
235
- extend_references[pin.namespace].push pin.name
236
- elsif pin.is_a?(Pin::Reference::Superclass)
237
- superclass_references[pin.namespace] ||= []
238
- superclass_references[pin.namespace].push pin.name
239
- elsif pin.is_a?(Pin::Block)
240
- block_pins.push pin
241
- elsif pin.is_a?(Pin::InstanceVariable)
242
- all_instance_variables.push pin
243
- elsif pin.is_a?(Pin::Reference::Override)
244
- override_pins.push pin
245
- end
246
- if pin.path
247
- path_pin_hash[pin.path] ||= []
248
- path_pin_hash[pin.path].push pin
249
- end
216
+ set = pins.to_set
217
+ @pin_class_hash = set.classify(&:class).transform_values(&:to_a)
218
+ @pin_select_cache = {}
219
+ @namespace_map = set.classify(&:namespace).transform_values(&:to_a)
220
+ @path_pin_hash = set.classify(&:path).transform_values(&:to_a)
221
+ @namespaces = @path_pin_hash.keys.compact
222
+ pins_by_class(Pin::Reference::Include).each do |pin|
223
+ include_references[pin.namespace] ||= []
224
+ include_references[pin.namespace].push pin.name
225
+ end
226
+ pins_by_class(Pin::Reference::Prepend).each do |pin|
227
+ prepend_references[pin.namespace] ||= []
228
+ prepend_references[pin.namespace].push pin.name
229
+ end
230
+ pins_by_class(Pin::Reference::Extend).each do |pin|
231
+ extend_references[pin.namespace] ||= []
232
+ extend_references[pin.namespace].push pin.name
233
+ end
234
+ pins_by_class(Pin::Reference::Superclass).each do |pin|
235
+ superclass_references[pin.namespace] ||= []
236
+ superclass_references[pin.namespace].push pin.name
250
237
  end
251
- override_pins.each do |ovr|
238
+ pins_by_class(Pin::Reference::Override).each do |ovr|
252
239
  pin = get_path_pins(ovr.name).first
253
240
  next if pin.nil?
254
241
  (ovr.tags.map(&:tag_name) + ovr.delete).uniq.each do |tag|
@@ -261,6 +248,7 @@ module Solargraph
261
248
  # @todo This is probably not the best place for these overrides
262
249
  superclass_references['Integer'] = ['Numeric']
263
250
  superclass_references['Float'] = ['Numeric']
251
+ superclass_references['File'] = ['IO']
264
252
  end
265
253
  end
266
254
  end
@@ -0,0 +1,9 @@
1
+ unless Hash.method_defined?(:transform_values)
2
+ class Hash
3
+ def transform_values &block
4
+ each_pair do |k, v|
5
+ self[k] = block.call(v)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -24,7 +24,8 @@ module Solargraph
24
24
  # @return [Array<Hash>]
25
25
  def diagnose source, _api_map
26
26
  options, paths = generate_options(source.filename, source.code)
27
- runner = RuboCop::Runner.new(options, RuboCop::ConfigStore.new)
27
+ store = RuboCop::ConfigStore.new
28
+ runner = RuboCop::Runner.new(options, store)
28
29
  result = redirect_stdout{ runner.run(paths) }
29
30
  make_array JSON.parse(result)
30
31
  rescue RuboCop::ValidationError, RuboCop::ConfigNotFoundError => e
@@ -17,7 +17,8 @@ module Solargraph
17
17
  rubocop_file = find_rubocop_file(filename)
18
18
  args.push('-c', fix_drive_letter(rubocop_file)) unless rubocop_file.nil?
19
19
  args.push filename
20
- options, paths = RuboCop::Options.new.parse(args)
20
+ base_options = RuboCop::Options.new
21
+ options, paths = base_options.parse(args)
21
22
  options[:stdin] = code
22
23
  [options, paths]
23
24
  end
@@ -27,6 +28,8 @@ module Solargraph
27
28
  # @param filename [String]
28
29
  # @return [String, nil]
29
30
  def find_rubocop_file filename
31
+ return nil unless File.exist?(filename)
32
+ filename = File.realpath(filename)
30
33
  dir = File.dirname(filename)
31
34
  until File.dirname(dir) == dir
32
35
  here = File.join(dir, '.rubocop.yml')
@@ -5,6 +5,7 @@ require 'json'
5
5
  require 'open3'
6
6
  require 'shellwords'
7
7
  require 'yard'
8
+ require 'fileutils'
8
9
 
9
10
  module Solargraph
10
11
  class Documentor
@@ -25,6 +26,7 @@ module Solargraph
25
26
  Documentor.specs_from_bundle(@directory).each_pair do |name, version|
26
27
  yd = YARD::Registry.yardoc_file_for_gem(name, "= #{version}")
27
28
  if !yd || @rebuild
29
+ FileUtils.safe_unlink File.join(YardMap::CoreDocs.cache_dir, 'gems', "#{name}-#{version}.ser")
28
30
  @out.puts "Documenting #{name} #{version}"
29
31
  `yard gems #{name} #{version} #{@rebuild ? '--rebuild' : ''}`
30
32
  yd = YARD::Registry.yardoc_file_for_gem(name, "= #{version}")
@@ -99,7 +99,7 @@ module Solargraph
99
99
  message = Message.select(request['method']).new(self, request)
100
100
  begin
101
101
  message.process
102
- rescue Exception => e
102
+ rescue StandardError => e
103
103
  logger.warn "Error processing request: [#{e.class}] #{e.message}"
104
104
  logger.warn e.backtrace.join("\n")
105
105
  message.set_error Solargraph::LanguageServer::ErrorCodes::INTERNAL_ERROR, "[#{e.class}] #{e.message}"
@@ -16,11 +16,15 @@ module Solargraph
16
16
  # detects the correct configuration
17
17
  # the .rb extension is needed for ruby file without extension, else rubocop won't format
18
18
  tempfile = File.join(File.dirname(filename), "_tmp_#{SecureRandom.hex(8)}_#{File.basename(filename)}.rb")
19
+ rubocop_file = Diagnostics::RubocopHelpers.find_rubocop_file(filename)
19
20
  original = host.read_text(params['textDocument']['uri'])
20
21
  File.write tempfile, original
21
22
  begin
22
- options, paths = RuboCop::Options.new.parse(['-a', '-f', 'fi', tempfile])
23
- redirect_stdout { RuboCop::Runner.new(options, RuboCop::ConfigStore.new).run(paths) }
23
+ args = ['-a', '-f', 'fi', tempfile]
24
+ args.unshift('-c', fix_drive_letter(rubocop_file)) unless rubocop_file.nil?
25
+ options, paths = RuboCop::Options.new.parse(args)
26
+ store = RuboCop::ConfigStore.new
27
+ redirect_stdout { RuboCop::Runner.new(options, store).run(paths) }
24
28
  result = File.read(tempfile)
25
29
  File.unlink tempfile
26
30
  format original, result
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'uri'
3
+ require 'cgi'
4
4
 
5
5
  module Solargraph
6
6
  module LanguageServer
@@ -14,7 +14,7 @@ module Solargraph
14
14
  # @param uri [String]
15
15
  # @return [String]
16
16
  def uri_to_file uri
17
- URI.decode(uri).sub(/^file\:\/\//, '').sub(/^\/([a-z]\:)/i, '\1')
17
+ decode(uri).sub(/^file\:\/\//, '').sub(/^\/([a-z]\:)/i, '\1')
18
18
  end
19
19
 
20
20
  # Convert a file path to a URI.
@@ -22,7 +22,27 @@ module Solargraph
22
22
  # @param file [String]
23
23
  # @return [String]
24
24
  def file_to_uri file
25
- "file://#{URI.encode(file.gsub(/^([a-z]\:)/i, '/\1'))}"
25
+ "file://#{encode(file.gsub(/^([a-z]\:)/i, '/\1'))}"
26
+ end
27
+
28
+ # Encode text to be used as a URI path component in LSP.
29
+ #
30
+ # @param text [String]
31
+ # @return [String]
32
+ def encode text
33
+ CGI.escape(text)
34
+ .gsub('%3A', ':')
35
+ .gsub('%5C', '\\')
36
+ .gsub('%2F', '/')
37
+ .gsub('+', '%20')
38
+ end
39
+
40
+ # Decode text from a URI path component in LSP.
41
+ #
42
+ # @param text [String]
43
+ # @return [String]
44
+ def decode text
45
+ CGI.unescape(text)
26
46
  end
27
47
  end
28
48
  end
@@ -36,6 +36,8 @@ module Solargraph
36
36
  process_prepend
37
37
  elsif node.children[1] == :require
38
38
  process_require
39
+ elsif node.children[1] == :autoload
40
+ process_autoload
39
41
  elsif node.children[1] == :private_constant
40
42
  process_private_constant
41
43
  elsif node.children[1] == :alias_method && node.children[2] && node.children[2] && node.children[2].type == :sym && node.children[3] && node.children[3].type == :sym
@@ -138,6 +140,14 @@ module Solargraph
138
140
  end
139
141
  end
140
142
 
143
+ # @return [void]
144
+ def process_autoload
145
+ if node.children[3].is_a?(AST::Node) && node.children[3].type == :str
146
+ path = node.children[3].children[0].to_s
147
+ pins.push Pin::Reference::Require.new(get_node_location(node), path)
148
+ end
149
+ end
150
+
141
151
  # @return [void]
142
152
  def process_module_function
143
153
  if node.children[2].nil?