solargraph 0.47.1 → 0.48.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7d697adb07ecb0f68c08da0001decead501d9c755bf79b3870c0e3f67c062d6c
4
- data.tar.gz: 191141aee5b75aa20a514bbc807df5c058823094afa99d9948bada9067c3eb8b
3
+ metadata.gz: 7531e9e085d6b9645a2d44a9aa020d661769a05ebe9b15377d91d0217f1cebd1
4
+ data.tar.gz: 63d27c2e39cac69742d77866ba7c5ef49634d8598cc10aa8427ec150bf70d12b
5
5
  SHA512:
6
- metadata.gz: fa47406469782b55edc3f75d6a4474d6730153333a40ac76092ca0586a7935f9ad36b44dfb641df35b48317c0e5fffb6d722dbe0df88833130da534c33ae80b6
7
- data.tar.gz: 5fb3c3e20abaa8b90375213601ec354ef936bfb7cc2f49fba44f6af3254e864ae38beaf6668186931a33fcd72d587fe5a29a67122cb3a65b2d85dd6deba6c147
6
+ metadata.gz: 38929be15a4be6b9995f7b471a9fed4f51541027822bd92b78b2f6ca426a9b42477491c324066ea312f31ebeb43a73a373a457454edc8c14390ab25f403c727d
7
+ data.tar.gz: 1c16b8046376cde3f1a1393ca12b060b708b4c5be1c1e9ee4f2be0f03b2443c6dcbc77bce3190ce47cff7fe2f7726e0963a3f05e00956dadd5628c2a437aeab3
data/CHANGELOG.md CHANGED
@@ -1,3 +1,18 @@
1
+ ## 0.48.0 - December 19, 2022
2
+ - Add Sublime Text to README (#604)
3
+ - Map nested constant assignments
4
+ - Handle rest/kwrest modifiers on overload arguments (#601)
5
+ - Make rubocop info severity Severity::HINT (#576)
6
+ - Process non-self singleton classes (#581)
7
+ - Fix nest gemspec dependency (#599)
8
+ - Strip 'file ' prefix from all filenames in RdocToYard (#585)
9
+ - Show why rubocop fails (#605)
10
+ - Link solargraph-rails (#611)
11
+
12
+ ## 0.47.2 - September 30, 2022
13
+ - Fix complex type inference (#578)
14
+ - Off-by-one diagnostic (#595)
15
+
1
16
  ## 0.47.1 - September 27, 2022
2
17
  - Remove debug code from release (#600)
3
18
 
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).
@@ -125,6 +125,13 @@ module Solargraph
125
125
  Solargraph::ComplexType.parse(fqns)
126
126
  end
127
127
  end
128
+
129
+ # @yieldparam [UniqueType]
130
+ # @return [Enumerator<UniqueType>]
131
+ def each_unique_type &block
132
+ return enum_for(__method__) unless block_given?
133
+ yield self
134
+ end
128
135
  end
129
136
  end
130
137
  end
@@ -40,6 +40,16 @@ module Solargraph
40
40
  @items.each &block
41
41
  end
42
42
 
43
+ # @yieldparam [UniqueType]
44
+ # @return [Enumerator<UniqueType>]
45
+ def each_unique_type &block
46
+ return enum_for(__method__) unless block_given?
47
+
48
+ @items.each do |item|
49
+ item.each_unique_type &block
50
+ end
51
+ end
52
+
43
53
  def length
44
54
  @items.length
45
55
  end
@@ -74,6 +84,10 @@ module Solargraph
74
84
  @items.all? &block
75
85
  end
76
86
 
87
+ def any? &block
88
+ @items.any? &block
89
+ end
90
+
77
91
  def selfy?
78
92
  @items.any?(&:selfy?)
79
93
  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,
@@ -31,7 +32,7 @@ module Solargraph
31
32
  rescue RuboCop::ValidationError, RuboCop::ConfigNotFoundError => e
32
33
  raise DiagnosticsError, "Error in RuboCop configuration: #{e.message}"
33
34
  rescue JSON::ParserError
34
- raise DiagnosticsError, 'RuboCop returned invalid data'
35
+ raise DiagnosticsError, "RuboCop returned invalid data: #{e.message}"
35
36
  end
36
37
 
37
38
  private
@@ -89,7 +90,7 @@ module Solargraph
89
90
  Position.new(off['location']['start_line'], 0)
90
91
  else
91
92
  Position.new(
92
- off['location']['start_line'] - 1, off['location']['last_column']
93
+ off['location']['start_line'] - 1, off['location']['last_column'] - 1
93
94
  )
94
95
  end
95
96
  end
@@ -8,16 +8,26 @@ module Solargraph
8
8
  include Legacy::NodeMethods
9
9
 
10
10
  def process
11
- here = get_node_start_position(node)
12
11
  pins.push Solargraph::Pin::Constant.new(
13
12
  location: get_node_location(node),
14
13
  closure: region.closure,
15
- name: node.children[1].to_s,
14
+ name: const_name,
16
15
  comments: comments_for(node),
17
16
  assignment: node.children[2]
18
17
  )
19
18
  process_children
20
19
  end
20
+
21
+ private
22
+
23
+ # @return [String]
24
+ def const_name
25
+ if node.children[0]
26
+ Parser::NodeMethods.unpack_name(node.children[0]) + "::#{node.children[1]}"
27
+ else
28
+ node.children[1].to_s
29
+ end
30
+ end
21
31
  end
22
32
  end
23
33
  end
@@ -6,11 +6,32 @@ module Solargraph
6
6
  module NodeProcessors
7
7
  class SclassNode < Parser::NodeProcessor::Base
8
8
  def process
9
- # @todo Temporarily skipping remote metaclasses
10
- return unless node.children[0].is_a?(AST::Node) && node.children[0].type == :self
9
+ sclass = node.children[0]
10
+ if sclass.is_a?(AST::Node) && sclass.type == :self
11
+ closure = region.closure
12
+ elsif sclass.is_a?(AST::Node) && sclass.type == :casgn
13
+ names = [region.closure.namespace, region.closure.name]
14
+ if sclass.children[0].nil? && names.last != sclass.children[1].to_s
15
+ names << sclass.children[1].to_s
16
+ else
17
+ names.concat [NodeMethods.unpack_name(sclass.children[0]), sclass.children[1].to_s]
18
+ end
19
+ name = names.reject(&:empty?).join('::')
20
+ closure = Solargraph::Pin::Namespace.new(name: name, location: region.closure.location)
21
+ elsif sclass.is_a?(AST::Node) && sclass.type == :const
22
+ names = [region.closure.namespace, region.closure.name]
23
+ also = NodeMethods.unpack_name(sclass)
24
+ if also != region.closure.name
25
+ names << also
26
+ end
27
+ name = names.reject(&:empty?).join('::')
28
+ closure = Solargraph::Pin::Namespace.new(name: name, location: region.closure.location)
29
+ else
30
+ return
31
+ end
11
32
  pins.push Solargraph::Pin::Singleton.new(
12
33
  location: get_node_location(node),
13
- closure: region.closure
34
+ closure: closure
14
35
  )
15
36
  process_children region.update(visibility: :public, scope: :class, closure: pins.last)
16
37
  end
@@ -9,12 +9,23 @@ module Solargraph
9
9
  pins.push Solargraph::Pin::Constant.new(
10
10
  location: get_node_location(node),
11
11
  closure: region.closure,
12
- name: node.children[0].to_s,
12
+ name: const_name,
13
13
  comments: comments_for(node),
14
- assignment: node.children[1]
14
+ assignment: node.children[2] || node.children[1]
15
15
  )
16
16
  process_children
17
17
  end
18
+
19
+ private
20
+
21
+ # @return [String]
22
+ def const_name
23
+ if Parser.is_ast_node?(node.children[0])
24
+ Parser::NodeMethods.unpack_name(node.children[0])
25
+ else
26
+ node.children[0].to_s
27
+ end
28
+ end
18
29
  end
19
30
  end
20
31
  end
@@ -6,11 +6,22 @@ module Solargraph
6
6
  module NodeProcessors
7
7
  class SclassNode < Parser::NodeProcessor::Base
8
8
  def process
9
- # @todo Temporarily skipping remote metaclasses
10
- return unless node.children[0].is_a?(RubyVM::AbstractSyntaxTree::Node) && node.children[0].type == :SELF
9
+ sclass = node.children[0]
10
+ if sclass.is_a?(RubyVM::AbstractSyntaxTree::Node) && sclass.type == :SELF
11
+ closure = region.closure
12
+ elsif sclass.is_a?(RubyVM::AbstractSyntaxTree::Node) && %i[CDECL CONST].include?(sclass.type)
13
+ names = [region.closure.namespace, region.closure.name]
14
+ if names.last != sclass.children[0].to_s
15
+ names << sclass.children[0].to_s
16
+ end
17
+ name = names.reject(&:empty?).join('::')
18
+ closure = Solargraph::Pin::Namespace.new(name: name, location: region.closure.location)
19
+ else
20
+ return
21
+ end
11
22
  pins.push Solargraph::Pin::Singleton.new(
12
23
  location: get_node_location(node),
13
- closure: region.closure
24
+ closure: closure
14
25
  )
15
26
  process_children region.update(visibility: :public, scope: :class, closure: pins.last)
16
27
  end
@@ -124,13 +124,14 @@ module Solargraph
124
124
  closure: self,
125
125
  # args: tag.parameters.map(&:first),
126
126
  parameters: tag.parameters.map do |src|
127
+ name, decl = parse_overload_param(src.first)
127
128
  Pin::Parameter.new(
128
129
  location: location,
129
130
  closure: self,
130
131
  comments: tag.docstring.all.to_s,
131
- name: src.first,
132
+ name: name,
132
133
  presence: location ? location.range : nil,
133
- decl: :arg
134
+ decl: decl
134
135
  )
135
136
  end,
136
137
  comments: tag.docstring.all.to_s
@@ -240,6 +241,21 @@ module Solargraph
240
241
  return ComplexType::UNDEFINED if types.empty?
241
242
  ComplexType.try_parse(*types.map(&:tag).uniq)
242
243
  end
244
+
245
+ # When YARD parses an overload tag, it includes rest modifiers in the parameters names.
246
+ #
247
+ # @param arg [String]
248
+ # @return [Array(String, Symbol)]
249
+ def parse_overload_param(name)
250
+ if name.start_with?('**')
251
+ [name[2..-1], :kwrestarg]
252
+ elsif name.start_with?('*')
253
+ [name[1..-1], :restarg]
254
+ else
255
+ [name, :arg]
256
+ end
257
+ end
258
+
243
259
  end
244
260
  end
245
261
  end
@@ -35,7 +35,10 @@ module Solargraph
35
35
  []
36
36
  end
37
37
  return inferred_pins(found, api_map, name_pin.context, locals) unless found.empty?
38
- pins = api_map.get_method_stack(name_pin.binder.namespace, word, scope: name_pin.binder.scope)
38
+ # @param [ComplexType::UniqueType]
39
+ pins = name_pin.binder.each_unique_type.flat_map do |context|
40
+ api_map.get_method_stack(context.namespace, word, scope: context.scope)
41
+ end
39
42
  return [] if pins.empty?
40
43
  inferred_pins(pins, api_map, name_pin.context, locals)
41
44
  end
@@ -61,6 +61,19 @@ module Solargraph
61
61
  false
62
62
  end
63
63
 
64
+ # @param api_map [ApiMap]
65
+ # @param inferred [ComplexType]
66
+ # @param expected [ComplexType]
67
+ # @return [Boolean]
68
+ def all_types_match? api_map, inferred, expected
69
+ return duck_types_match?(api_map, expected, inferred) if expected.duck_type?
70
+ inferred.each do |inf|
71
+ next if inf.duck_type?
72
+ return false unless expected.any? { |exp| exp == inf || either_way?(api_map, inf, exp) }
73
+ end
74
+ true
75
+ end
76
+
64
77
  # @param api_map [ApiMap]
65
78
  # @param expected [ComplexType]
66
79
  # @param inferred [ComplexType]
@@ -105,7 +105,7 @@ module Solargraph
105
105
  result.push Problem.new(pin.location, "#{pin.path} return type could not be inferred", pin: pin)
106
106
  end
107
107
  else
108
- unless (rules.rank > 1 ? types_match?(api_map, declared, inferred) : any_types_match?(api_map, declared, inferred))
108
+ unless (rules.rank > 1 ? all_types_match?(api_map, inferred, declared) : any_types_match?(api_map, declared, inferred))
109
109
  result.push Problem.new(pin.location, "Declared return type #{declared} does not match inferred type #{inferred} for #{pin.path}", pin: pin)
110
110
  end
111
111
  end
@@ -177,7 +177,7 @@ module Solargraph
177
177
  result.push Problem.new(pin.location, "Variable type could not be inferred for #{pin.name}", pin: pin)
178
178
  end
179
179
  else
180
- unless (rules.rank > 1 ? types_match?(api_map, declared, inferred) : any_types_match?(api_map, declared, inferred))
180
+ unless any_types_match?(api_map, declared, inferred)
181
181
  result.push Problem.new(pin.location, "Declared type #{declared} does not match inferred type #{inferred} for variable #{pin.name}", pin: pin)
182
182
  end
183
183
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Solargraph
4
- VERSION = '0.47.1'
4
+ VERSION = '0.48.0'
5
5
  end
@@ -129,11 +129,14 @@ module Solargraph
129
129
  end
130
130
 
131
131
  def self.find_file obj
132
- if obj.respond_to?(:in_files) && !obj.in_files.empty?
133
- [obj.in_files.first.to_s.sub(/^file /, ''), obj.line]
132
+ file = if obj.respond_to?(:in_files) && !obj.in_files.empty?
133
+ obj.in_files.first
134
134
  else
135
- [obj.file, obj.line]
135
+ obj.file
136
136
  end
137
+
138
+ file = file.to_s.sub(/^file /, '') unless file.nil?
139
+ [file, obj.line]
137
140
  end
138
141
  end
139
142
  end
@@ -214,30 +214,7 @@ module Solargraph
214
214
  pins.concat cached
215
215
  next
216
216
  end
217
- result = []
218
- begin
219
- spec = spec_for_require(r)
220
- if @source_gems.include?(spec.name)
221
- next
222
- end
223
- next if @gem_paths.key?(spec.name)
224
- yd = yardoc_file_for_spec(spec)
225
- # YARD detects gems for certain libraries that do not have a yardoc
226
- # but exist in the stdlib. `fileutils` is an example. Treat those
227
- # cases as errors and check the stdlib yardoc.
228
- if yd.nil?
229
- process_error(r, result, already_errored, nil)
230
- next
231
- end
232
- @gem_paths[spec.name] = spec.full_gem_path
233
- unless yardocs.include?(yd)
234
- yardocs.unshift yd
235
- result.concat process_yardoc yd, spec
236
- result.concat add_gem_dependencies(spec) if with_dependencies?
237
- end
238
- rescue Gem::LoadError, NoYardocError
239
- process_error(r, result, already_errored)
240
- end
217
+ result = pins_for_require r, already_errored
241
218
  result.delete_if(&:nil?)
242
219
  unless result.empty?
243
220
  cache.set_path_pins r, result
@@ -273,31 +250,36 @@ module Solargraph
273
250
  require_from_bundle(directory)
274
251
  end
275
252
 
276
- # @param spec [Gem::Specification]
277
- # @return [void]
278
- def add_gem_dependencies spec
253
+ # @param r [String]
254
+ def pins_for_require r, already_errored
279
255
  result = []
280
- (spec.dependencies - spec.development_dependencies).each do |dep|
281
- begin
282
- next if @source_gems.include?(dep.name) || @gem_paths.key?(dep.name)
283
- depspec = Gem::Specification.find_by_name(dep.name)
284
- next if depspec.nil?
285
- @gem_paths[depspec.name] = depspec.full_gem_path
286
- gy = yardoc_file_for_spec(depspec)
287
- if gy.nil?
288
- missing_docs.push dep.name
289
- else
290
- next if yardocs.include?(gy)
291
- yardocs.unshift gy
292
- result.concat process_yardoc gy, depspec
293
- result.concat add_gem_dependencies(depspec)
256
+ begin
257
+ name = r.split('/').first
258
+ return [] if @source_gems.include?(name) || @gem_paths.key?(name)
259
+ spec = spec_for_require(name)
260
+ @gem_paths[name] = spec.full_gem_path
261
+
262
+ yd = yardoc_file_for_spec(spec)
263
+ # YARD detects gems for certain libraries that do not have a yardoc
264
+ # but exist in the stdlib. `fileutils` is an example. Treat those
265
+ # cases as errors and check the stdlib yardoc.
266
+ if yd.nil?
267
+ process_error(r, result, already_errored, nil)
268
+ return []
269
+ end
270
+ unless yardocs.include?(yd)
271
+ yardocs.unshift yd
272
+ result.concat process_yardoc yd, spec
273
+ if with_dependencies?
274
+ (spec.dependencies - spec.development_dependencies).each do |dep|
275
+ result.concat pins_for_require dep.name, already_errored
276
+ end
294
277
  end
295
- rescue Gem::LoadError
296
- # This error probably indicates a bug in an installed gem
297
- Solargraph::Logging.logger.warn "Failed to resolve #{dep.name} gem dependency for #{spec.name}"
298
278
  end
279
+ rescue Gem::LoadError, NoYardocError
280
+ process_error(r, result, already_errored)
299
281
  end
300
- result
282
+ return result
301
283
  end
302
284
 
303
285
  # @param y [String, nil]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solargraph
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.47.1
4
+ version: 0.48.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fred Snyder
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-09-27 00:00:00.000000000 Z
11
+ date: 2022-12-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: backport