solargraph 0.48.0 → 0.50.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +1 -0
  3. data/.github/workflows/rspec.yml +1 -1
  4. data/CHANGELOG.md +29 -0
  5. data/LICENSE +1 -1
  6. data/README.md +2 -4
  7. data/SPONSORS.md +4 -4
  8. data/lib/solargraph/api_map/store.rb +13 -1
  9. data/lib/solargraph/api_map.rb +30 -12
  10. data/lib/solargraph/cache.rb +53 -0
  11. data/lib/solargraph/complex_type/type_methods.rb +3 -6
  12. data/lib/solargraph/complex_type/unique_type.rb +57 -0
  13. data/lib/solargraph/complex_type.rb +22 -3
  14. data/lib/solargraph/convention/rakefile.rb +17 -0
  15. data/lib/solargraph/convention.rb +2 -0
  16. data/lib/solargraph/diagnostics/rubocop.rb +15 -2
  17. data/lib/solargraph/diagnostics/rubocop_helpers.rb +3 -1
  18. data/lib/solargraph/language_server/host/cataloger.rb +1 -1
  19. data/lib/solargraph/language_server/host.rb +22 -18
  20. data/lib/solargraph/language_server/message/extended/download_core.rb +1 -5
  21. data/lib/solargraph/language_server/message/initialize.rb +2 -0
  22. data/lib/solargraph/language_server/message/text_document/formatting.rb +1 -1
  23. data/lib/solargraph/language_server/message/text_document/signature_help.rb +1 -6
  24. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +10 -3
  25. data/lib/solargraph/library.rb +25 -20
  26. data/lib/solargraph/parser/rubyvm/class_methods.rb +6 -1
  27. data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +20 -8
  28. data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +14 -3
  29. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +4 -2
  30. data/lib/solargraph/parser/rubyvm/node_wrapper.rb +47 -0
  31. data/lib/solargraph/pin/base.rb +5 -2
  32. data/lib/solargraph/pin/base_variable.rb +1 -1
  33. data/lib/solargraph/pin/conversions.rb +2 -6
  34. data/lib/solargraph/pin/method.rb +84 -10
  35. data/lib/solargraph/pin/namespace.rb +4 -1
  36. data/lib/solargraph/pin/parameter.rb +8 -3
  37. data/lib/solargraph/pin/signature.rb +23 -0
  38. data/lib/solargraph/pin.rb +1 -0
  39. data/lib/solargraph/rbs_map/conversions.rb +394 -0
  40. data/lib/solargraph/rbs_map/core_fills.rb +61 -0
  41. data/lib/solargraph/rbs_map/core_map.rb +38 -0
  42. data/lib/solargraph/rbs_map/core_signs.rb +33 -0
  43. data/lib/solargraph/rbs_map/stdlib_map.rb +36 -0
  44. data/lib/solargraph/rbs_map.rb +73 -0
  45. data/lib/solargraph/shell.rb +50 -32
  46. data/lib/solargraph/source/chain/call.rb +31 -23
  47. data/lib/solargraph/source/chain.rb +22 -7
  48. data/lib/solargraph/source_map/clip.rb +5 -0
  49. data/lib/solargraph/source_map/mapper.rb +8 -4
  50. data/lib/solargraph/type_checker.rb +71 -65
  51. data/lib/solargraph/version.rb +1 -1
  52. data/lib/solargraph/views/environment.erb +2 -2
  53. data/lib/solargraph/workspace.rb +11 -14
  54. data/lib/solargraph/yard_map/mapper/to_method.rb +7 -4
  55. data/lib/solargraph/yard_map.rb +10 -151
  56. data/lib/solargraph.rb +2 -2
  57. data/solargraph.gemspec +11 -6
  58. metadata +46 -37
  59. data/.travis.yml +0 -19
  60. data/lib/solargraph/compat.rb +0 -37
  61. data/lib/solargraph/yard_map/core_docs.rb +0 -170
  62. data/lib/solargraph/yard_map/core_fills.rb +0 -208
  63. data/lib/solargraph/yard_map/core_gen.rb +0 -76
  64. data/lib/solargraph/yard_map/rdoc_to_yard.rb +0 -143
  65. data/lib/solargraph/yard_map/stdlib_fills.rb +0 -43
  66. data/yardoc/2.2.2.tar.gz +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7531e9e085d6b9645a2d44a9aa020d661769a05ebe9b15377d91d0217f1cebd1
4
- data.tar.gz: 63d27c2e39cac69742d77866ba7c5ef49634d8598cc10aa8427ec150bf70d12b
3
+ metadata.gz: 3a6e7990068e276537a53e6af24d45685d73aba32af134def16d8a66ea671f64
4
+ data.tar.gz: 57292437f34d43394a161fe4909eb27931d5d33e1b367276faecc7b0132525e9
5
5
  SHA512:
6
- metadata.gz: 38929be15a4be6b9995f7b471a9fed4f51541027822bd92b78b2f6ca426a9b42477491c324066ea312f31ebeb43a73a373a457454edc8c14390ab25f403c727d
7
- data.tar.gz: 1c16b8046376cde3f1a1393ca12b060b708b4c5be1c1e9ee4f2be0f03b2443c6dcbc77bce3190ce47cff7fe2f7726e0963a3f05e00956dadd5628c2a437aeab3
6
+ metadata.gz: 1d751b364593fa60cc51c3b9a67086c7a8006dcfe37107daaba4ca1db3f001da28eb289978d81fbe7e84c3a5c9add902417731479517be61269acd958456a057
7
+ data.tar.gz: 1c38faac70a696f81c5063d5ef64341a41a8d244c47c070ab557dbef8e4ca2180f5c22d5d0338c4b6f24598ea27850895bed2eab7c4d747b7bb2efeb71309eb2
@@ -0,0 +1 @@
1
+ patreon: castwide
@@ -22,7 +22,7 @@ jobs:
22
22
  runs-on: ubuntu-latest
23
23
  strategy:
24
24
  matrix:
25
- ruby-version: ['2.4', '2.5', '2.6', '2.7', '3.0']
25
+ ruby-version: ['2.6', '2.7', '3.0', '3.1']
26
26
 
27
27
  steps:
28
28
  - uses: actions/checkout@v3
data/CHANGELOG.md CHANGED
@@ -1,3 +1,32 @@
1
+ ## 0.50.0 - December 5, 2023
2
+ - Remove .travis.yml as its not longer used (#627)
3
+ - Fix empty string case when processing requires (#644)
4
+ - Fix scope() method call on wrong object (#670)
5
+ - Parse comments that start with multiple hashes (#667)
6
+ - Use XDG_CACHE_HOME if it exists (#664)
7
+ - Add rbs mention to readme (#693)
8
+ - Remove Atom from the readme (#692)
9
+ - Add more metadata to the gemspec (#691)
10
+ - Do not deprecate clear command
11
+ - Library#locate_ref returns nil for unresolved requires (#675)
12
+ - Hide deprecated commands
13
+ - List command
14
+ - Fixes (or ignores) ffi crash (#676)
15
+ - increase sleep time on cataloger (#677)
16
+ - YardMap ignores absolute paths (#678)
17
+ - Clarify macros vs. directives
18
+ - Infer complex types from method calls
19
+ - Default cache uses XDG_CACHE_HOME default (#664)
20
+
21
+ ## 0.49.0 - April 9, 2023
22
+ - Better union type handling
23
+ - First version of RBS support
24
+ - Dependency updates
25
+ - Update RuboCop config options
26
+ - RBS core and stdlib mapping
27
+ - Anonymous splats and multisig arity
28
+ - Infinite loop when checking if a class is a superclass (#641)
29
+
1
30
  ## 0.48.0 - December 19, 2022
2
31
  - Add Sublime Text to README (#604)
3
32
  - Map nested constant assignments
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2017-2019 by Fred Snyder for Castwide Technologies
3
+ Copyright (c) 2017-2023 by Fred Snyder for Castwide Technologies
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -28,10 +28,6 @@ Plug-ins and extensions are available for the following editors:
28
28
  * Extension: https://marketplace.visualstudio.com/items?itemName=castwide.solargraph
29
29
  * GitHub: https://github.com/castwide/vscode-solargraph
30
30
 
31
- * **Atom**
32
- * Package: https://atom.io/packages/ruby-solargraph
33
- * GitHub: https://github.com/castwide/atom-solargraph
34
-
35
31
  * **Sublime Text**
36
32
  * Extension: https://packagecontrol.io/packages/LSP
37
33
  * GitHub: https://github.com/sublimelsp/LSP
@@ -71,6 +67,8 @@ As of version 0.33.0, Solargraph includes a [type checker](https://github.com/ca
71
67
 
72
68
  ### Updating Core Documentation
73
69
 
70
+ As of version 0.49.0, Solargraph uses [rbs](https://github.com/ruby/rbs) for core and stdlib documentation. The following only applies to prior versions.
71
+
74
72
  The Solargraph gem ships with documentation for Ruby 2.2.2. You can download documentation for other Ruby versions from the command line.
75
73
 
76
74
  $ solargraph list-cores # List the installed documentation versions
data/SPONSORS.md CHANGED
@@ -7,11 +7,11 @@ The following people and organizations provide funding or other resources. [Beco
7
7
  ## Linked Sponsors
8
8
 
9
9
  - **[Calyptix Security](https://www.calyptix.com/)**
10
+ - **[Lightward](https://lightward.com)**
10
11
 
11
12
  ## Named Sponsors
12
13
 
13
- - Tom de Grunt
14
14
  - Akira Yamada
15
- - Erlend Finvåg
16
- - Matt Massicotte
17
- - Oscar Rivas
15
+ - Jesus Castello
16
+ - Joel Drapper
17
+ - Spencer
@@ -247,10 +247,22 @@ module Solargraph
247
247
  end
248
248
  ovr.tags.each do |tag|
249
249
  pin.docstring.add_tag(tag)
250
- new_pin.docstring.add_tag(tag) if new_pin
250
+ redefine_return_type pin, tag
251
+ if new_pin
252
+ new_pin.docstring.add_tag(tag)
253
+ redefine_return_type new_pin, tag
254
+ end
251
255
  end
252
256
  end
253
257
  end
258
+
259
+ def redefine_return_type pin, tag
260
+ return unless pin && tag.tag_name == 'return'
261
+ pin.instance_variable_set(:@return_type, ComplexType.try_parse(tag.type))
262
+ pin.signatures.each do |sig|
263
+ sig.instance_variable_set(:@return_type, ComplexType.try_parse(tag.type))
264
+ end
265
+ end
254
266
  end
255
267
  end
256
268
  end
@@ -21,6 +21,8 @@ module Solargraph
21
21
  # @return [Array<String>]
22
22
  attr_reader :unresolved_requires
23
23
 
24
+ @@core_map = RbsMap::CoreMap.new
25
+
24
26
  # @return [Array<String>]
25
27
  attr_reader :missing_docs
26
28
 
@@ -40,7 +42,7 @@ module Solargraph
40
42
  @source_map_hash = {}
41
43
  implicit.clear
42
44
  cache.clear
43
- @store = Store.new(yard_map.pins + pins)
45
+ @store = Store.new(@@core_map.pins + pins)
44
46
  self
45
47
  end
46
48
 
@@ -68,8 +70,10 @@ module Solargraph
68
70
  end
69
71
  external_requires.merge implicit.requires
70
72
  external_requires.merge bench.workspace.config.required
71
- yard_map.change(external_requires, bench.workspace.directory, bench.workspace.source_gems)
72
- @store = Store.new(yard_map.pins + implicit.pins + pins)
73
+ @rbs_maps = external_requires.map { |r| load_rbs_map(r) }
74
+ unresolved_requires = @rbs_maps.reject(&:resolved?).map(&:library)
75
+ yard_map.change(unresolved_requires, bench.workspace.directory, bench.workspace.source_gems)
76
+ @store = Store.new(@@core_map.pins + @rbs_maps.flat_map(&:pins) + yard_map.pins + implicit.pins + pins)
73
77
  @unresolved_requires = yard_map.unresolved_requires
74
78
  @missing_docs = yard_map.missing_docs
75
79
  @rebindable_method_names = nil
@@ -77,6 +81,14 @@ module Solargraph
77
81
  self
78
82
  end
79
83
 
84
+ def core_pins
85
+ @@core_map.pins
86
+ end
87
+
88
+ def yard_map
89
+ @yard_map ||= YardMap.new
90
+ end
91
+
80
92
  # @param name [String]
81
93
  # @return [YARD::Tags::MacroDirective, nil]
82
94
  def named_macro name
@@ -132,7 +144,8 @@ module Solargraph
132
144
 
133
145
  def rebindable_method_names
134
146
  @rebindable_method_names ||= begin
135
- result = yard_map.rebindable_method_names
147
+ # result = yard_map.rebindable_method_names
148
+ result = ['instance_eval', 'instance_exec', 'class_eval', 'class_exec', 'module_eval', 'module_exec', 'define_method'].to_set
136
149
  source_maps.each do |map|
137
150
  result.merge map.rebindable_method_names
138
151
  end
@@ -191,7 +204,7 @@ module Solargraph
191
204
  #
192
205
  # @param namespace [String, nil] The namespace to match
193
206
  # @param context [String] The context to search
194
- # @return [String]
207
+ # @return [String, nil]
195
208
  def qualify namespace, context = ''
196
209
  return namespace if ['self', nil].include?(namespace)
197
210
  cached = cache.get_qualified_namespace(namespace, context)
@@ -447,18 +460,15 @@ module Solargraph
447
460
  def super_and_sub?(sup, sub)
448
461
  fqsup = qualify(sup)
449
462
  cls = qualify(sub)
450
- until fqsup.nil? || cls.nil?
463
+ tested = []
464
+ until fqsup.nil? || cls.nil? || tested.include?(cls)
451
465
  return true if cls == fqsup
466
+ tested.push cls
452
467
  cls = qualify_superclass(cls)
453
468
  end
454
469
  false
455
470
  end
456
471
 
457
- # @return [YardMap]
458
- def yard_map
459
- @yard_map ||= YardMap.new
460
- end
461
-
462
472
  # Check if the host class includes the specified module.
463
473
  #
464
474
  # @param host [String] The class
@@ -475,6 +485,14 @@ module Solargraph
475
485
  # @return [Hash{String => SourceMap}]
476
486
  attr_reader :source_map_hash
477
487
 
488
+ # @param library [String]
489
+ # @return [RbsMap]
490
+ def load_rbs_map library
491
+ # map = RbsMap.load(library)
492
+ # return map if map.resolved?
493
+ RbsMap::StdlibMap.load(library)
494
+ end
495
+
478
496
  # @return [ApiMap::Store]
479
497
  def store
480
498
  @store ||= Store.new
@@ -677,7 +695,7 @@ module Solargraph
677
695
  comments: origin.comments,
678
696
  scope: origin.scope,
679
697
  visibility: origin.visibility,
680
- parameters: origin.parameters,
698
+ signatures: origin.signatures,
681
699
  attribute: origin.attribute?
682
700
  }
683
701
  Pin::Method.new **args
@@ -0,0 +1,53 @@
1
+ require 'fileutils'
2
+
3
+ module Solargraph
4
+ module Cache
5
+ class << self
6
+ # The base directory where cached documentation is installed.
7
+ #
8
+ # @return [String]
9
+ def base_dir
10
+ # The directory is not stored in a variable so it can be overridden
11
+ # in specs.
12
+ ENV['SOLARGRAPH_CACHE'] ||
13
+ ENV['XDG_CACHE_HOME'] ? File.join(ENV['XDG_CACHE_HOME'], 'solargraph') :
14
+ File.join(Dir.home, '.cache', 'solargraph')
15
+ end
16
+
17
+ # The working directory for the current Ruby and Solargraph versions.
18
+ #
19
+ # @return [String]
20
+ def work_dir
21
+ # The directory is not stored in a variable so it can be overridden
22
+ # in specs.
23
+ File.join(base_dir, "ruby-#{RUBY_VERSION}", "rbs-#{RBS::VERSION}", "solargraph-#{Solargraph::VERSION}")
24
+ end
25
+
26
+ # @return [Array<Solargraph::Pin::Base>, nil]
27
+ def load *path
28
+ file = File.join(work_dir, *path)
29
+ return nil unless File.file?(file)
30
+ Marshal.load(File.read(file, mode: 'rb'))
31
+ rescue StandardError => e
32
+ Solargraph.logger.warn "Failed to load cached file #{file}: [#{e.class}] #{e.message}"
33
+ FileUtils.rm_f file
34
+ nil
35
+ end
36
+
37
+ # @return [Boolean]
38
+ def save *path, pins
39
+ return false if pins.empty?
40
+ file = File.join(work_dir, *path)
41
+ base = File.dirname(file)
42
+ FileUtils.mkdir_p base unless File.directory?(base)
43
+ ser = Marshal.dump(pins)
44
+ File.write file, ser, mode: 'wb'
45
+ true
46
+ end
47
+
48
+ def clear
49
+ FileUtils.rm_rf base_dir, secure: true
50
+ end
51
+ end
52
+ end
53
+ end
@@ -101,6 +101,7 @@ module Solargraph
101
101
  # @param context [String] The namespace from which to resolve names
102
102
  # @return [ComplexType] The generated ComplexType
103
103
  def qualify api_map, context = ''
104
+ return self if name == 'param'
104
105
  return ComplexType.new([self]) if duck_type? || void? || undefined?
105
106
  recon = (rooted? ? '' : context)
106
107
  fqns = api_map.qualify(name, recon)
@@ -109,12 +110,8 @@ module Solargraph
109
110
  return UniqueType::UNDEFINED
110
111
  end
111
112
  fqns = "::#{fqns}" # Ensure the resulting complex type is rooted
112
- ltypes = key_types.map do |t|
113
- t.qualify api_map, context
114
- end
115
- rtypes = value_types.map do |t|
116
- t.qualify api_map, context
117
- end
113
+ ltypes = key_types.map { |t| t.qualify api_map, context }.uniq
114
+ rtypes = value_types.map { |t| t.qualify api_map, context }.uniq
118
115
  if list_parameters?
119
116
  Solargraph::ComplexType.parse("#{fqns}<#{rtypes.map(&:tag).join(', ')}>")
120
117
  elsif fixed_parameters?
@@ -8,6 +8,8 @@ module Solargraph
8
8
  class UniqueType
9
9
  include TypeMethods
10
10
 
11
+ attr_reader :all_params
12
+
11
13
  # Create a UniqueType with the specified name and an optional substring.
12
14
  # The substring is the parameter section of a parametrized type, e.g.,
13
15
  # for the type `Array<String>`, the name is `Array` and the substring is
@@ -27,6 +29,7 @@ module Solargraph
27
29
  @tag = @name + substring
28
30
  @key_types = []
29
31
  @subtypes = []
32
+ @all_params = []
30
33
  return unless parameters?
31
34
  if @substring.start_with?('<(') && @substring.end_with?(')>')
32
35
  subs = ComplexType.parse(substring[2..-3], partial: true)
@@ -40,12 +43,66 @@ module Solargraph
40
43
  else
41
44
  @subtypes.concat subs
42
45
  end
46
+ @all_params.concat @key_types
47
+ @all_params.concat @subtypes
43
48
  end
44
49
 
45
50
  def to_s
46
51
  tag
47
52
  end
48
53
 
54
+ def to_rbs
55
+ "#{namespace}#{parameters? ? "[#{subtypes.map { |s| s.to_rbs }.join(', ')}]" : ''}"
56
+ end
57
+
58
+ def parameterized?
59
+ name == 'param' || all_params.any?(&:parameterized?)
60
+ end
61
+
62
+ def resolve_parameters definitions, context
63
+ new_name = if name == 'param'
64
+ idx = definitions.parameters.index(subtypes.first.name)
65
+ return ComplexType::UNDEFINED if idx.nil?
66
+ param_type = context.return_type.all_params[idx]
67
+ return ComplexType::UNDEFINED unless param_type
68
+ param_type.to_s
69
+ else
70
+ name
71
+ end
72
+ new_key_types = if name != 'param'
73
+ @key_types.map { |t| t.resolve_parameters(definitions, context) }.select(&:defined?)
74
+ else
75
+ []
76
+ end
77
+ new_subtypes = if name != 'param'
78
+ @subtypes.map { |t| t.resolve_parameters(definitions, context) }.select(&:defined?)
79
+ else
80
+ []
81
+ end
82
+ if name != 'param' && !(new_key_types.empty? && new_subtypes.empty?)
83
+ if hash_parameters?
84
+ UniqueType.new(new_name, "{#{new_key_types.join(', ')} => #{new_subtypes.join(', ')}}")
85
+ elsif parameters?
86
+ if @substring.start_with?'<('
87
+ UniqueType.new(new_name, "<(#{new_subtypes.join(', ')})>")
88
+ else
89
+ UniqueType.new(new_name, "<#{new_subtypes.join(', ')}>")
90
+ end
91
+ else
92
+ UniqueType.new(new_name)
93
+ end
94
+ else
95
+ UniqueType.new(new_name)
96
+ end
97
+
98
+ # idx = definitions.parameters.index(subtypes.first.name)
99
+ # STDERR.puts "Index: #{idx}"
100
+ # return ComplexType::UNDEFINED if idx.nil?
101
+ # param_type = context.return_type.all_params[idx]
102
+ # return ComplexType::UNDEFINED unless param_type
103
+ # ComplexType.try_parse(param_type.to_s)
104
+ end
105
+
49
106
  def self_to dst
50
107
  return self unless selfy?
51
108
  new_name = (@name == 'self' ? dst : @name)
@@ -30,6 +30,12 @@ module Solargraph
30
30
  @items.first
31
31
  end
32
32
 
33
+ def to_rbs
34
+ ((@items.length > 1 ? '(' : '') + @items.map do |item|
35
+ "#{item.namespace}#{item.parameters? ? "[#{item.subtypes.map { |s| s.to_rbs }.join(', ')}]" : ''}"
36
+ end.join(' | ') + (@items.length > 1 ? ')' : '')).gsub(/undefined/, 'untyped')
37
+ end
38
+
33
39
  def map &block
34
40
  @items.map &block
35
41
  end
@@ -85,26 +91,39 @@ module Solargraph
85
91
  end
86
92
 
87
93
  def any? &block
88
- @items.any? &block
94
+ @items.compact.any? &block
89
95
  end
90
96
 
91
97
  def selfy?
92
98
  @items.any?(&:selfy?)
93
99
  end
94
100
 
101
+ def parameterized?
102
+ any?(&:parameterized?)
103
+ end
104
+
105
+ def resolve_parameters definitions, context
106
+ result = @items.map { |i| i.resolve_parameters(definitions, context) }
107
+ ComplexType.parse(*result.map(&:tag))
108
+ end
109
+
95
110
  # @param dst [String]
96
111
  # @return [ComplexType]
97
112
  def self_to dst
98
113
  return self unless selfy?
99
114
  red = reduce_class(dst)
100
115
  result = @items.map { |i| i.self_to red }
101
- ComplexType.parse(*result.map(&:tag))
116
+ ComplexType.parse(*result.map(&:to_s))
102
117
  end
103
118
 
104
119
  def nullable?
105
120
  @items.any?(&:nil_type?)
106
121
  end
107
122
 
123
+ def all_params
124
+ @items.first.all_params || []
125
+ end
126
+
108
127
  private
109
128
 
110
129
  # @todo This is a quick and dirty hack that forces `self` keywords
@@ -150,7 +169,7 @@ module Solargraph
150
169
  paren_stack = 0
151
170
  base = String.new
152
171
  subtype_string = String.new
153
- type_string.each_char do |char|
172
+ type_string&.each_char do |char|
154
173
  if char == '='
155
174
  #raise ComplexTypeError, "Invalid = in type #{type_string}" unless curly_stack > 0
156
175
  elsif char == '<'
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Convention
5
+ class Rakefile < Base
6
+ def local source_map
7
+ basename = File.basename(source_map.filename)
8
+ return EMPTY_ENVIRON unless basename.end_with?('.rake') || basename == 'Rakefile'
9
+
10
+ @environ ||= Environ.new(
11
+ requires: ['rake'],
12
+ domains: ['Rake::DSL']
13
+ )
14
+ end
15
+ end
16
+ end
17
+ end
@@ -11,6 +11,7 @@ module Solargraph
11
11
  autoload :Gemfile, 'solargraph/convention/gemfile'
12
12
  autoload :Rspec, 'solargraph/convention/rspec'
13
13
  autoload :Gemspec, 'solargraph/convention/gemspec'
14
+ autoload :Rakefile, 'solargraph/convention/rakefile'
14
15
 
15
16
  @@conventions = Set.new
16
17
 
@@ -43,5 +44,6 @@ module Solargraph
43
44
  register Gemfile
44
45
  register Gemspec
45
46
  register Rspec
47
+ register Rakefile
46
48
  end
47
49
  end
@@ -23,15 +23,19 @@ module Solargraph
23
23
  # @param _api_map [Solargraph::ApiMap]
24
24
  # @return [Array<Hash>]
25
25
  def diagnose source, _api_map
26
+ @source = source
26
27
  require_rubocop(rubocop_version)
27
28
  options, paths = generate_options(source.filename, source.code)
28
29
  store = RuboCop::ConfigStore.new
29
30
  runner = RuboCop::Runner.new(options, store)
30
31
  result = redirect_stdout{ runner.run(paths) }
32
+
33
+ return [] if result.empty?
34
+
31
35
  make_array JSON.parse(result)
32
36
  rescue RuboCop::ValidationError, RuboCop::ConfigNotFoundError => e
33
37
  raise DiagnosticsError, "Error in RuboCop configuration: #{e.message}"
34
- rescue JSON::ParserError
38
+ rescue JSON::ParserError => e
35
39
  raise DiagnosticsError, "RuboCop returned invalid data: #{e.message}"
36
40
  end
37
41
 
@@ -89,8 +93,17 @@ module Solargraph
89
93
  if off['location']['start_line'] != off['location']['last_line']
90
94
  Position.new(off['location']['start_line'], 0)
91
95
  else
96
+ start_line = off['location']['start_line'] - 1
97
+ last_column = off['location']['last_column']
98
+ line = @source.code.lines[start_line]
99
+ col_off = if line.nil? || line.empty?
100
+ 1
101
+ else
102
+ 0
103
+ end
104
+
92
105
  Position.new(
93
- off['location']['start_line'] - 1, off['location']['last_column'] - 1
106
+ start_line, last_column - col_off
94
107
  )
95
108
  end
96
109
  end
@@ -10,13 +10,15 @@ module Solargraph
10
10
  # Requires a specific version of rubocop, or the latest installed version
11
11
  # if _version_ is `nil`.
12
12
  #
13
- # @param version [String]
13
+ # @param version [String, nil]
14
14
  # @raise [InvalidRubocopVersionError] if _version_ is not installed
15
15
  def require_rubocop(version = nil)
16
16
  begin
17
17
  gem_path = Gem::Specification.find_by_name('rubocop', version).full_gem_path
18
18
  gem_lib_path = File.join(gem_path, 'lib')
19
19
  $LOAD_PATH.unshift(gem_lib_path) unless $LOAD_PATH.include?(gem_lib_path)
20
+ # @todo Gem::MissingSpecVersionError is undocumented for some reason
21
+ # @sg-ignore
20
22
  rescue Gem::MissingSpecVersionError => e
21
23
  raise InvalidRubocopVersionError,
22
24
  "could not find '#{e.name}' (#{e.requirement}) - "\
@@ -34,7 +34,7 @@ module Solargraph
34
34
  Thread.new do
35
35
  until stopped?
36
36
  tick
37
- sleep 0.01
37
+ sleep 0.1
38
38
  end
39
39
  end
40
40
  end
@@ -130,35 +130,39 @@ module Solargraph
130
130
  end
131
131
  end
132
132
 
133
- # Respond to a notification that a file was created in the workspace.
134
- # The libraries will determine whether the file should be merged; see
133
+ # Respond to a notification that files were created in the workspace.
134
+ # The libraries will determine whether the files should be merged; see
135
135
  # Solargraph::Library#create_from_disk.
136
136
  #
137
- # @param uri [String] The file uri.
138
- # @return [Boolean] True if a library accepted the file.
139
- def create uri
140
- filename = uri_to_file(uri)
137
+ # @param uris [Array<String>] The URIs of the files.
138
+ # @return [Boolean] True if at least one library accepted at least one file.
139
+ def create *uris
140
+ filenames = uris.map { |uri| uri_to_file(uri) }
141
141
  result = false
142
142
  libraries.each do |lib|
143
- result = true if lib.create_from_disk(filename)
143
+ result = true if lib.create_from_disk(*filenames)
144
+ end
145
+ uris.each do |uri|
146
+ diagnoser.schedule uri if open?(uri)
144
147
  end
145
- diagnoser.schedule uri if open?(uri)
146
148
  result
147
149
  end
148
150
 
149
- # Delete the specified file from the library.
151
+ # Delete the specified files from the library.
150
152
  #
151
- # @param uri [String] The file uri.
153
+ # @param uris [Array<String>] The file uris.
152
154
  # @return [void]
153
- def delete uri
154
- filename = uri_to_file(uri)
155
+ def delete *uris
156
+ filenames = uris.map { |uri| uri_to_file(uri) }
155
157
  libraries.each do |lib|
156
- lib.delete(filename)
158
+ lib.delete(*filenames)
159
+ end
160
+ uris.each do |uri|
161
+ send_notification "textDocument/publishDiagnostics", {
162
+ uri: uri,
163
+ diagnostics: []
164
+ }
157
165
  end
158
- send_notification "textDocument/publishDiagnostics", {
159
- uri: uri,
160
- diagnostics: []
161
- }
162
166
  end
163
167
 
164
168
  # Open the specified file in the library.
@@ -692,7 +696,7 @@ module Solargraph
692
696
  params['contentChanges'].each do |recvd|
693
697
  chng = check_diff(params['textDocument']['uri'], recvd)
694
698
  changes.push Solargraph::Source::Change.new(
695
- (chng['range'].nil? ?
699
+ (chng['range'].nil? ?
696
700
  nil :
697
701
  Solargraph::Range.from_to(chng['range']['start']['line'], chng['range']['start']['character'], chng['range']['end']['line'], chng['range']['end']['character'])
698
702
  ),
@@ -10,11 +10,7 @@ module Solargraph
10
10
  #
11
11
  class DownloadCore < Base
12
12
  def process
13
- ver = Solargraph::YardMap::CoreDocs.best_download
14
- Solargraph::YardMap::CoreDocs.download ver
15
- host.show_message "Downloaded documentation for Ruby #{ver}.", LanguageServer::MessageTypes::INFO
16
- rescue StandardError => e
17
- host.show_message "An error occurred while downloading documentation: [#{e.class}] #{e.message}", LanguageServer::MessageTypes::ERROR
13
+ host.show_message "Downloading cores is deprecated. Solargraph currently uses RBS for core and stdlib documentation", LanguageServer::MessageTypes::INFO
18
14
  end
19
15
  end
20
16
  end
@@ -25,6 +25,8 @@ module Solargraph
25
25
  }
26
26
  }
27
27
  }
28
+ # FIXME: lsp default is utf-16, may have different position
29
+ result[:capabilities][:positionEncoding] = "utf-32" if params.dig("capabilities", "general", "positionEncodings")&.include?("utf-32")
28
30
  result[:capabilities].merge! static_completion unless dynamic_registration_for?('textDocument', 'completion')
29
31
  result[:capabilities].merge! static_signature_help unless dynamic_registration_for?('textDocument', 'signatureHelp')
30
32
  # result[:capabilities].merge! static_on_type_formatting unless dynamic_registration_for?('textDocument', 'onTypeFormatting')
@@ -54,7 +54,7 @@ module Solargraph
54
54
  def cli_args file_uri, config
55
55
  file = UriHelpers.uri_to_file(file_uri)
56
56
  args = [
57
- config['cops'] == 'all' ? '--auto-correct-all' : '--auto-correct',
57
+ config['cops'] == 'all' ? '--autocorrect-all' : '--autocorrect',
58
58
  '--cache', 'false',
59
59
  '--format', formatter_class(config).name,
60
60
  ]