solargraph 0.47.2 → 0.49.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) 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 +20 -0
  5. data/LICENSE +1 -1
  6. data/README.md +8 -0
  7. data/SPONSORS.md +2 -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 +51 -0
  11. data/lib/solargraph/complex_type/type_methods.rb +10 -6
  12. data/lib/solargraph/complex_type/unique_type.rb +57 -0
  13. data/lib/solargraph/complex_type.rb +30 -1
  14. data/lib/solargraph/convention/rakefile.rb +17 -0
  15. data/lib/solargraph/convention.rb +2 -0
  16. data/lib/solargraph/diagnostics/rubocop.rb +17 -3
  17. data/lib/solargraph/diagnostics/rubocop_helpers.rb +3 -1
  18. data/lib/solargraph/language_server/host.rb +22 -18
  19. data/lib/solargraph/language_server/message/extended/download_core.rb +1 -5
  20. data/lib/solargraph/language_server/message/initialize.rb +2 -0
  21. data/lib/solargraph/language_server/message/text_document/formatting.rb +1 -1
  22. data/lib/solargraph/language_server/message/text_document/signature_help.rb +1 -6
  23. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +10 -3
  24. data/lib/solargraph/library.rb +21 -20
  25. data/lib/solargraph/parser/legacy/node_processors/casgn_node.rb +12 -2
  26. data/lib/solargraph/parser/legacy/node_processors/sclass_node.rb +24 -3
  27. data/lib/solargraph/parser/rubyvm/class_methods.rb +6 -1
  28. data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +13 -2
  29. data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +20 -8
  30. data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +14 -3
  31. data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +14 -3
  32. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +4 -2
  33. data/lib/solargraph/parser/rubyvm/node_wrapper.rb +47 -0
  34. data/lib/solargraph/pin/base.rb +5 -2
  35. data/lib/solargraph/pin/conversions.rb +2 -6
  36. data/lib/solargraph/pin/method.rb +100 -10
  37. data/lib/solargraph/pin/namespace.rb +4 -1
  38. data/lib/solargraph/pin/parameter.rb +8 -3
  39. data/lib/solargraph/pin/signature.rb +23 -0
  40. data/lib/solargraph/pin.rb +1 -0
  41. data/lib/solargraph/rbs_map/conversions.rb +394 -0
  42. data/lib/solargraph/rbs_map/core_fills.rb +61 -0
  43. data/lib/solargraph/rbs_map/core_map.rb +38 -0
  44. data/lib/solargraph/rbs_map/core_signs.rb +33 -0
  45. data/lib/solargraph/rbs_map/stdlib_map.rb +36 -0
  46. data/lib/solargraph/rbs_map.rb +73 -0
  47. data/lib/solargraph/shell.rb +38 -30
  48. data/lib/solargraph/source/chain/call.rb +34 -23
  49. data/lib/solargraph/source/chain.rb +21 -6
  50. data/lib/solargraph/source_map/clip.rb +5 -0
  51. data/lib/solargraph/source_map/mapper.rb +2 -0
  52. data/lib/solargraph/type_checker.rb +71 -65
  53. data/lib/solargraph/version.rb +1 -1
  54. data/lib/solargraph/views/environment.erb +2 -2
  55. data/lib/solargraph/workspace.rb +11 -14
  56. data/lib/solargraph/yard_map/mapper/to_method.rb +7 -4
  57. data/lib/solargraph/yard_map.rb +34 -193
  58. data/lib/solargraph.rb +2 -2
  59. data/solargraph.gemspec +8 -6
  60. metadata +43 -36
  61. data/lib/solargraph/compat.rb +0 -37
  62. data/lib/solargraph/yard_map/core_docs.rb +0 -170
  63. data/lib/solargraph/yard_map/core_fills.rb +0 -208
  64. data/lib/solargraph/yard_map/core_gen.rb +0 -76
  65. data/lib/solargraph/yard_map/rdoc_to_yard.rb +0 -140
  66. data/lib/solargraph/yard_map/stdlib_fills.rb +0 -43
  67. data/yardoc/2.2.2.tar.gz +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9d35030ae56f6aaff108a24e4fb06713f911ba4366feb2223b24ad0ea4568522
4
- data.tar.gz: a9eeaee16171bc762922ac55d10c61d53bcfe6ef1df0b20623c81e0978a80c7d
3
+ metadata.gz: b0b66abd5cf5a0376d5521532dda16db328592eb38bac6acd84f997b19cb328c
4
+ data.tar.gz: 51e038df27bae1457393c7ff023c9951b0f8919267678e29aab2e21efeb2b1a8
5
5
  SHA512:
6
- metadata.gz: 0b13ae6284def50f72c9aaed3cad6f89e879306dc8421b1c13f622e18181e6d9aaecf4f57ffa56601a00c92066557bb798d3e8ee6a397920ff0072f909e05463
7
- data.tar.gz: 9a0366309ebe9a4a784c2933a8452e2084c376ff9aa3cd6c3bf555f4d6ce046f11245679c688bef43c6c1e67d94b70afb4250149c9b01b80fc525b80a80b6486
6
+ metadata.gz: 9b8310748d4754c27fd62763ce1bd8759fc43fc825b1b40353d4537130f2b6143cdb59101da679a8b4a7fb0778430eeac2eccbb845f7a9a5ac11f402b3a71461
7
+ data.tar.gz: 1b2f79f5396a3c056d0b2acbcb49d6c1385b02a49b33edbe1a3e452a7b451b9b87547b8b8d5974a17e25ea2f5c21db8dd315d2b3d856fb3c7ce2d300a4595c70
@@ -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,23 @@
1
+ ## 0.49.0 - April 9, 2023
2
+ - Better union type handling
3
+ - First version of RBS support
4
+ - Dependency updates
5
+ - Update RuboCop config options
6
+ - RBS core and stdlib mapping
7
+ - Anonymous splats and multisig arity
8
+ - Infinite loop when checking if a class is a superclass (#641)
9
+
10
+ ## 0.48.0 - December 19, 2022
11
+ - Add Sublime Text to README (#604)
12
+ - Map nested constant assignments
13
+ - Handle rest/kwrest modifiers on overload arguments (#601)
14
+ - Make rubocop info severity Severity::HINT (#576)
15
+ - Process non-self singleton classes (#581)
16
+ - Fix nest gemspec dependency (#599)
17
+ - Strip 'file ' prefix from all filenames in RdocToYard (#585)
18
+ - Show why rubocop fails (#605)
19
+ - Link solargraph-rails (#611)
20
+
1
21
  ## 0.47.2 - September 30, 2022
2
22
  - Fix complex type inference (#578)
3
23
  - Off-by-one diagnostic (#595)
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
@@ -32,6 +32,11 @@ Plug-ins and extensions are available for the following editors:
32
32
  * Package: https://atom.io/packages/ruby-solargraph
33
33
  * GitHub: https://github.com/castwide/atom-solargraph
34
34
 
35
+ * **Sublime Text**
36
+ * Extension: https://packagecontrol.io/packages/LSP
37
+ * GitHub: https://github.com/sublimelsp/LSP
38
+ * Instructions: https://lsp.sublimetext.io/language_servers/#solargraph
39
+
35
40
  * **Vim**
36
41
  * GitHub: `LanguageClient-neovim`, https://github.com/autozimu/LanguageClient-neovim
37
42
  * GitHub: `coc`, https://github.com/neoclide/coc-solargraph
@@ -49,6 +54,9 @@ Plug-ins and extensions are available for the following editors:
49
54
 
50
55
  Solargraph's behavior can be controlled via optional [configuration](https://solargraph.org/guides/configuration) files. The highest priority file is a `.solargraph.yml` file at the root of the project. If not present, any global configuration at `~/.config/solargraph/config.yml` will apply. The path to the global configuration can be overridden with the `SOLARGRAPH_GLOBAL_CONFIG` environment variable.
51
56
 
57
+ ### Rails Support
58
+ For better Rails support, please consider using [solargraph-rails](https://github.com/iftheshoefritz/solargraph-rails/)
59
+
52
60
  ### Gem Support
53
61
 
54
62
  Solargraph is capable of providing code completion and documentation for gems that have YARD documentation. You can make sure your gems are documented by running `yard gems` from the command line. (YARD is included as one of Solargraph's gem dependencies. The first time you run it might take a while if you have a lot of gems installed).
data/SPONSORS.md CHANGED
@@ -10,8 +10,6 @@ The following people and organizations provide funding or other resources. [Beco
10
10
 
11
11
  ## Named Sponsors
12
12
 
13
- - Tom de Grunt
14
13
  - Akira Yamada
15
- - Erlend Finvåg
16
- - Matt Massicotte
17
- - Oscar Rivas
14
+ - Joel Drapper
15
+ - Yutaka Tachibana
@@ -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,51 @@
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'] || File.join(Dir.home, '.solargraph', 'cache')
13
+ end
14
+
15
+ # The working directory for the current Ruby and Solargraph versions.
16
+ #
17
+ # @return [String]
18
+ def work_dir
19
+ # The directory is not stored in a variable so it can be overridden
20
+ # in specs.
21
+ File.join(base_dir, "ruby-#{RUBY_VERSION}", "rbs-#{RBS::VERSION}", "solargraph-#{Solargraph::VERSION}")
22
+ end
23
+
24
+ # @return [Array<Solargraph::Pin::Base>, nil]
25
+ def load *path
26
+ file = File.join(work_dir, *path)
27
+ return nil unless File.file?(file)
28
+ Marshal.load(File.read(file, mode: 'rb'))
29
+ rescue StandardError => e
30
+ Solargraph.logger.warn "Failed to load cached file #{file}: [#{e.class}] #{e.message}"
31
+ FileUtils.rm_f file
32
+ nil
33
+ end
34
+
35
+ # @return [Boolean]
36
+ def save *path, pins
37
+ return false if pins.empty?
38
+ file = File.join(work_dir, *path)
39
+ base = File.dirname(file)
40
+ FileUtils.mkdir_p base unless File.directory?(base)
41
+ ser = Marshal.dump(pins)
42
+ File.write file, ser, mode: 'wb'
43
+ true
44
+ end
45
+
46
+ def clear
47
+ FileUtils.rm_rf base_dir, secure: true
48
+ end
49
+ end
50
+ end
51
+ 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?
@@ -125,6 +122,13 @@ module Solargraph
125
122
  Solargraph::ComplexType.parse(fqns)
126
123
  end
127
124
  end
125
+
126
+ # @yieldparam [UniqueType]
127
+ # @return [Enumerator<UniqueType>]
128
+ def each_unique_type &block
129
+ return enum_for(__method__) unless block_given?
130
+ yield self
131
+ end
128
132
  end
129
133
  end
130
134
  end
@@ -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
@@ -40,6 +46,16 @@ module Solargraph
40
46
  @items.each &block
41
47
  end
42
48
 
49
+ # @yieldparam [UniqueType]
50
+ # @return [Enumerator<UniqueType>]
51
+ def each_unique_type &block
52
+ return enum_for(__method__) unless block_given?
53
+
54
+ @items.each do |item|
55
+ item.each_unique_type &block
56
+ end
57
+ end
58
+
43
59
  def length
44
60
  @items.length
45
61
  end
@@ -75,13 +91,22 @@ module Solargraph
75
91
  end
76
92
 
77
93
  def any? &block
78
- @items.any? &block
94
+ @items.compact.any? &block
79
95
  end
80
96
 
81
97
  def selfy?
82
98
  @items.any?(&:selfy?)
83
99
  end
84
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
+
85
110
  # @param dst [String]
86
111
  # @return [ComplexType]
87
112
  def self_to dst
@@ -95,6 +120,10 @@ module Solargraph
95
120
  @items.any?(&:nil_type?)
96
121
  end
97
122
 
123
+ def all_params
124
+ @items.first.all_params || []
125
+ end
126
+
98
127
  private
99
128
 
100
129
  # @todo This is a quick and dirty hack that forces `self` keywords
@@ -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
@@ -11,6 +11,7 @@ module Solargraph
11
11
 
12
12
  # Conversion of RuboCop severity names to LSP constants
13
13
  SEVERITIES = {
14
+ 'info' => Severities::HINT,
14
15
  'refactor' => Severities::HINT,
15
16
  'convention' => Severities::INFORMATION,
16
17
  'warning' => Severities::WARNING,
@@ -22,16 +23,20 @@ module Solargraph
22
23
  # @param _api_map [Solargraph::ApiMap]
23
24
  # @return [Array<Hash>]
24
25
  def diagnose source, _api_map
26
+ @source = source
25
27
  require_rubocop(rubocop_version)
26
28
  options, paths = generate_options(source.filename, source.code)
27
29
  store = RuboCop::ConfigStore.new
28
30
  runner = RuboCop::Runner.new(options, store)
29
31
  result = redirect_stdout{ runner.run(paths) }
32
+
33
+ return [] if result.empty?
34
+
30
35
  make_array JSON.parse(result)
31
36
  rescue RuboCop::ValidationError, RuboCop::ConfigNotFoundError => e
32
37
  raise DiagnosticsError, "Error in RuboCop configuration: #{e.message}"
33
- rescue JSON::ParserError
34
- raise DiagnosticsError, 'RuboCop returned invalid data'
38
+ rescue JSON::ParserError => e
39
+ raise DiagnosticsError, "RuboCop returned invalid data: #{e.message}"
35
40
  end
36
41
 
37
42
  private
@@ -88,8 +93,17 @@ module Solargraph
88
93
  if off['location']['start_line'] != off['location']['last_line']
89
94
  Position.new(off['location']['start_line'], 0)
90
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
+
91
105
  Position.new(
92
- off['location']['start_line'] - 1, off['location']['last_column'] - 1
106
+ start_line, last_column - col_off
93
107
  )
94
108
  end
95
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}) - "\
@@ -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
  ]