solargraph 0.54.1 → 0.54.3

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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +17 -0
  3. data/lib/solargraph/api_map/cache.rb +10 -1
  4. data/lib/solargraph/api_map/index.rb +167 -0
  5. data/lib/solargraph/api_map/store.rb +48 -120
  6. data/lib/solargraph/api_map.rb +76 -20
  7. data/lib/solargraph/complex_type/type_methods.rb +7 -0
  8. data/lib/solargraph/complex_type/unique_type.rb +21 -1
  9. data/lib/solargraph/complex_type.rb +13 -12
  10. data/lib/solargraph/convention.rb +1 -0
  11. data/lib/solargraph/doc_map.rb +1 -0
  12. data/lib/solargraph/equality.rb +33 -0
  13. data/lib/solargraph/language_server/host/message_worker.rb +23 -6
  14. data/lib/solargraph/language_server/host.rb +12 -11
  15. data/lib/solargraph/language_server/message/base.rb +19 -12
  16. data/lib/solargraph/language_server/message/initialize.rb +3 -1
  17. data/lib/solargraph/language_server/message/text_document/completion.rb +0 -3
  18. data/lib/solargraph/language_server/message/text_document/formatting.rb +4 -0
  19. data/lib/solargraph/library.rb +3 -2
  20. data/lib/solargraph/location.rb +7 -0
  21. data/lib/solargraph/parser/node_methods.rb +1 -1
  22. data/lib/solargraph/parser/node_processor.rb +1 -0
  23. data/lib/solargraph/parser/parser_gem/node_chainer.rb +3 -3
  24. data/lib/solargraph/parser/parser_gem/node_methods.rb +2 -2
  25. data/lib/solargraph/pin/base.rb +28 -18
  26. data/lib/solargraph/pin/base_variable.rb +3 -2
  27. data/lib/solargraph/pin/block.rb +1 -3
  28. data/lib/solargraph/pin/callable.rb +3 -3
  29. data/lib/solargraph/pin/method.rb +6 -0
  30. data/lib/solargraph/pin/namespace.rb +1 -1
  31. data/lib/solargraph/pin/parameter.rb +2 -1
  32. data/lib/solargraph/position.rb +7 -0
  33. data/lib/solargraph/range.rb +7 -0
  34. data/lib/solargraph/rbs_map/conversions.rb +8 -2
  35. data/lib/solargraph/rbs_map.rb +1 -0
  36. data/lib/solargraph/shell.rb +2 -0
  37. data/lib/solargraph/source/chain/array.rb +1 -1
  38. data/lib/solargraph/source/chain/call.rb +15 -8
  39. data/lib/solargraph/source/chain/hash.rb +5 -0
  40. data/lib/solargraph/source/chain/if.rb +5 -0
  41. data/lib/solargraph/source/chain/link.rb +17 -5
  42. data/lib/solargraph/source/chain/literal.rb +5 -0
  43. data/lib/solargraph/source/chain.rb +33 -19
  44. data/lib/solargraph/source/cursor.rb +2 -1
  45. data/lib/solargraph/source.rb +2 -1
  46. data/lib/solargraph/source_map/clip.rb +1 -1
  47. data/lib/solargraph/type_checker.rb +8 -8
  48. data/lib/solargraph/version.rb +1 -1
  49. data/lib/solargraph/workspace/config.rb +7 -3
  50. data/lib/solargraph/workspace.rb +1 -1
  51. data/lib/solargraph/yard_map/mapper/to_constant.rb +1 -0
  52. data/lib/solargraph/yard_map/mapper/to_namespace.rb +1 -0
  53. data/lib/solargraph/yard_map/mapper.rb +1 -0
  54. data/lib/solargraph.rb +1 -0
  55. data/solargraph.gemspec +5 -5
  56. metadata +26 -24
@@ -7,9 +7,15 @@ module Solargraph
7
7
  #
8
8
  class UniqueType
9
9
  include TypeMethods
10
+ include Equality
10
11
 
11
12
  attr_reader :all_params, :subtypes, :key_types
12
13
 
14
+ # @sg-ignore Fix "Not enough arguments to Module#protected"
15
+ protected def equality_fields
16
+ [@name, @all_params, @subtypes, @key_types]
17
+ end
18
+
13
19
  # Create a UniqueType with the specified name and an optional substring.
14
20
  # The substring is the parameter section of a parametrized type, e.g.,
15
21
  # for the type `Array<String>`, the name is `Array` and the substring is
@@ -112,6 +118,10 @@ module Solargraph
112
118
  end
113
119
  end
114
120
 
121
+ def desc
122
+ rooted_tags
123
+ end
124
+
115
125
  # @return [String]
116
126
  def to_rbs
117
127
  if duck_type?
@@ -235,7 +245,17 @@ module Solargraph
235
245
  if t.name == GENERIC_TAG_NAME
236
246
  idx = definitions.generics.index(t.subtypes.first&.name)
237
247
  next t if idx.nil?
238
- context_type.all_params[idx] || ComplexType::UNDEFINED
248
+ if context_type.parameters_type == :hash
249
+ if idx == 0
250
+ next ComplexType.new(context_type.key_types)
251
+ elsif idx == 1
252
+ next ComplexType.new(context_type.subtypes)
253
+ else
254
+ next ComplexType::UNDEFINED
255
+ end
256
+ else
257
+ context_type.all_params[idx] || ComplexType::UNDEFINED
258
+ end
239
259
  else
240
260
  t
241
261
  end
@@ -7,6 +7,7 @@ module Solargraph
7
7
  GENERIC_TAG_NAME = 'generic'.freeze
8
8
  # @!parse
9
9
  # include TypeMethods
10
+ include Equality
10
11
 
11
12
  autoload :TypeMethods, 'solargraph/complex_type/type_methods'
12
13
  autoload :UniqueType, 'solargraph/complex_type/unique_type'
@@ -18,17 +19,9 @@ module Solargraph
18
19
  @items = types.flat_map(&:items).uniq(&:to_s)
19
20
  end
20
21
 
21
- def eql?(other)
22
- self.class == other.class &&
23
- @items == other.items
24
- end
25
-
26
- def ==(other)
27
- self.eql?(other)
28
- end
29
-
30
- def hash
31
- [self.class, @items].hash
22
+ # @sg-ignore Fix "Not enough arguments to Module#protected"
23
+ protected def equality_fields
24
+ [self.class, items]
32
25
  end
33
26
 
34
27
  # @param api_map [ApiMap]
@@ -154,14 +147,22 @@ module Solargraph
154
147
  map(&:tag).join(', ')
155
148
  end
156
149
 
150
+ def desc
151
+ rooted_tags
152
+ end
153
+
157
154
  def rooted_tags
158
155
  map(&:rooted_tag).join(', ')
159
156
  end
160
157
 
158
+ # @yieldparam [UniqueType]
161
159
  def all? &block
162
160
  @items.all? &block
163
161
  end
164
162
 
163
+ # @yieldparam [UniqueType]
164
+ # @yieldreturn [Boolean]
165
+ # @return [Boolean]
165
166
  def any? &block
166
167
  @items.compact.any? &block
167
168
  end
@@ -263,7 +264,7 @@ module Solargraph
263
264
  # Consumers should not need to use this parameter; it should only be
264
265
  # used internally.
265
266
  #
266
- # @param *strings [Array<String>] The type definitions to parse
267
+ # @param strings [Array<String>] The type definitions to parse
267
268
  # @return [ComplexType]
268
269
  # # @overload parse(*strings, partial: false)
269
270
  # # @todo Need ability to use a literal true as a type below
@@ -11,6 +11,7 @@ module Solargraph
11
11
  autoload :Gemspec, 'solargraph/convention/gemspec'
12
12
  autoload :Rakefile, 'solargraph/convention/rakefile'
13
13
 
14
+ # @type [Set<Convention::Base>]
14
15
  @@conventions = Set.new
15
16
 
16
17
  # @param convention [Class<Convention::Base>]
@@ -112,6 +112,7 @@ module Solargraph
112
112
  true
113
113
  end
114
114
 
115
+ # @param gemspec [Gem::Specification]
115
116
  def update_from_collection gemspec, gempins
116
117
  return gempins unless @rbs_path && File.directory?(@rbs_path)
117
118
  return gempins if RbsMap.new(gemspec.name, gemspec.version).resolved?
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ # @abstract This mixin relies on these -
5
+ # methods:
6
+ # equality_fields()
7
+ module Equality
8
+ # @!method equality_fields
9
+ # @return [Array]
10
+
11
+ # @param other [Object]
12
+ # @return [Boolean]
13
+ def eql?(other)
14
+ self.class.eql?(other.class) &&
15
+ equality_fields.eql?(other.equality_fields)
16
+ end
17
+
18
+ # @param other [Object]
19
+ # @return [Boolean]
20
+ def ==(other)
21
+ self.eql?(other)
22
+ end
23
+
24
+ def hash
25
+ equality_fields.hash
26
+ end
27
+
28
+ def freeze
29
+ equality_fields.each(&:freeze)
30
+ super
31
+ end
32
+ end
33
+ end
@@ -3,12 +3,14 @@
3
3
  module Solargraph
4
4
  module LanguageServer
5
5
  class Host
6
- # A serial worker Thread to handle message.
7
- #
8
- # this make check pending message possible, and maybe cancelled to speedup process
6
+ # A serial worker Thread to handle incoming messages.
9
7
  #
10
8
  class MessageWorker
11
- UPDATE_METHODS = ['textDocument/didOpen', 'textDocument/didChange', 'workspace/didChangeWatchedFiles'].freeze
9
+ UPDATE_METHODS = [
10
+ 'textDocument/didOpen',
11
+ 'textDocument/didChange',
12
+ 'workspace/didChangeWatchedFiles'
13
+ ].freeze
12
14
 
13
15
  # @param host [Host]
14
16
  def initialize(host)
@@ -64,12 +66,24 @@ module Solargraph
64
66
  private
65
67
 
66
68
  def next_message
69
+ cancel_message || next_priority
70
+ end
71
+
72
+ def cancel_message
73
+ # Handle cancellations first
74
+ idx = messages.find_index { |msg| msg['method'] == '$/cancelRequest' }
75
+ return unless idx
76
+
77
+ msg = messages[idx]
78
+ messages.delete_at idx
79
+ msg
80
+ end
81
+
82
+ def next_priority
67
83
  # Prioritize updates and version-dependent messages for performance
68
84
  idx = messages.find_index do |msg|
69
85
  UPDATE_METHODS.include?(msg['method']) || version_dependent?(msg)
70
86
  end
71
- # @todo We might want to clear duplicate instances of this message
72
- # that occur before the next update
73
87
  return messages.shift unless idx
74
88
 
75
89
  msg = messages[idx]
@@ -80,6 +94,9 @@ module Solargraph
80
94
  # True if the message requires a previous update to have executed in
81
95
  # order to work correctly.
82
96
  #
97
+ # @param msg [Hash{String => Object}]
98
+ # @todo need boolish type from RBS
99
+ # @return [Object]
83
100
  def version_dependent? msg
84
101
  msg['textDocument'] && msg['position']
85
102
  end
@@ -24,10 +24,8 @@ module Solargraph
24
24
  attr_writer :client_capabilities
25
25
 
26
26
  def initialize
27
- @cancel_semaphore = Mutex.new
28
27
  @buffer_semaphore = Mutex.new
29
28
  @request_mutex = Mutex.new
30
- @cancel = []
31
29
  @buffer = String.new
32
30
  @stopped = true
33
31
  @next_request_id = 1
@@ -65,7 +63,7 @@ module Solargraph
65
63
  # @param id [Integer]
66
64
  # @return [void]
67
65
  def cancel id
68
- @cancel_semaphore.synchronize { @cancel.push id }
66
+ cancelled.push id
69
67
  end
70
68
 
71
69
  # True if the host received a request to cancel the method with the
@@ -74,9 +72,7 @@ module Solargraph
74
72
  # @param id [Integer]
75
73
  # @return [Boolean]
76
74
  def cancel? id
77
- result = false
78
- @cancel_semaphore.synchronize { result = @cancel.include? id }
79
- result
75
+ cancelled.include? id
80
76
  end
81
77
 
82
78
  # Delete the specified ID from the list of cancelled IDs if it exists.
@@ -84,7 +80,7 @@ module Solargraph
84
80
  # @param id [Integer]
85
81
  # @return [void]
86
82
  def clear id
87
- @cancel_semaphore.synchronize { @cancel.delete id }
83
+ cancelled.delete id
88
84
  end
89
85
 
90
86
  # Called by adapter, to handle the request
@@ -101,11 +97,11 @@ module Solargraph
101
97
  # @return [Solargraph::LanguageServer::Message::Base, nil] The message handler.
102
98
  def receive request
103
99
  if request['method']
104
- logger.info "Server received #{request['method']}"
100
+ logger.info "Host received ##{request['id']} #{request['method']}"
105
101
  logger.debug request
106
102
  message = Message.select(request['method']).new(self, request)
107
103
  begin
108
- message.process
104
+ message.process unless cancel?(request['id'])
109
105
  rescue StandardError => e
110
106
  logger.warn "Error processing request: [#{e.class}] #{e.message}"
111
107
  logger.warn e.backtrace.join("\n")
@@ -381,7 +377,6 @@ module Solargraph
381
377
  envelope = "Content-Length: #{json.bytesize}\r\n\r\n#{json}"
382
378
  queue envelope
383
379
  @next_request_id += 1
384
- logger.info "Server sent #{method}"
385
380
  logger.debug params
386
381
  end
387
382
  end
@@ -476,6 +471,7 @@ module Solargraph
476
471
  def locate_pins params
477
472
  return [] unless params['data'] && params['data']['uri']
478
473
  library = library_for(params['data']['uri'])
474
+ # @type [Array<Pin::Base>]
479
475
  result = []
480
476
  if params['data']['location']
481
477
  location = Location.new(
@@ -575,7 +571,7 @@ module Solargraph
575
571
  # @param column [Integer]
576
572
  # @param strip [Boolean] Strip special characters from variable names
577
573
  # @param only [Boolean] If true, search current file only
578
- # @return [Array<Solargraph::Range>]
574
+ # @return [Array<Solargraph::Location>]
579
575
  def references_from uri, line, column, strip: true, only: false
580
576
  library = library_for(uri)
581
577
  library.references_from(uri_to_file(uri), line, column, strip: strip, only: only)
@@ -693,6 +689,11 @@ module Solargraph
693
689
 
694
690
  private
695
691
 
692
+ # @return [Array<Integer>]
693
+ def cancelled
694
+ @cancelled ||= []
695
+ end
696
+
696
697
  # @return [MessageWorker]
697
698
  def message_worker
698
699
  @message_worker ||= MessageWorker.new(self)
@@ -16,7 +16,7 @@ module Solargraph
16
16
  # @return [String]
17
17
  attr_reader :method
18
18
 
19
- # @return [Hash{String => Array, Hash, String, Integer}]
19
+ # @return [Hash{String => Array<undefined>, Hash{String => undefined}, String, Integer}]
20
20
  attr_reader :params
21
21
 
22
22
  # @return [Hash, Array, nil]
@@ -61,18 +61,11 @@ module Solargraph
61
61
  # @return [void]
62
62
  def send_response
63
63
  return if id.nil?
64
- if host.cancel?(id)
65
- # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#cancelRequest
66
- # cancel should send response RequestCancelled
67
- Solargraph::Logging.logger.info "Cancelled response to #{method}"
68
- set_result nil
69
- set_error ErrorCodes::REQUEST_CANCELLED, "cancelled by client"
70
- else
71
- Solargraph::Logging.logger.info "Sending response to #{method}"
72
- end
64
+
65
+ accept_or_cancel
73
66
  response = {
74
- jsonrpc: "2.0",
75
- id: id,
67
+ jsonrpc: '2.0',
68
+ id: id
76
69
  }
77
70
  response[:result] = result unless result.nil?
78
71
  response[:error] = error unless error.nil?
@@ -83,6 +76,20 @@ module Solargraph
83
76
  host.queue envelope
84
77
  host.clear id
85
78
  end
79
+
80
+ private
81
+
82
+ def accept_or_cancel
83
+ if host.cancel?(id)
84
+ # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#cancelRequest
85
+ # cancel should send response RequestCancelled
86
+ Solargraph::Logging.logger.info "Cancelled response to ##{id} #{method}"
87
+ set_result nil
88
+ set_error ErrorCodes::REQUEST_CANCELLED, 'Cancelled by client'
89
+ else
90
+ Solargraph::Logging.logger.info "Sending response to ##{id} #{method}"
91
+ end
92
+ end
86
93
  end
87
94
  end
88
95
  end
@@ -174,7 +174,9 @@ module Solargraph
174
174
 
175
175
  # @param section [String]
176
176
  # @param capability [String]
177
- # @return [Boolean]
177
+ # @todo Need support for RBS' boolish "type", which doesn't
178
+ # enforce strict true/false-ness
179
+ # @sg-ignore
178
180
  def dynamic_registration_for? section, capability
179
181
  result = (params['capabilities'] &&
180
182
  params['capabilities'][section] &&
@@ -12,9 +12,6 @@ module Solargraph
12
12
  col = params['position']['character']
13
13
  begin
14
14
  completion = host.completions_at(params['textDocument']['uri'], line, col)
15
- if host.cancel?(id)
16
- return set_result(empty_result) if host.cancel?(id)
17
- end
18
15
  items = []
19
16
  last_context = nil
20
17
  idx = -1
@@ -33,6 +33,7 @@ module Solargraph
33
33
 
34
34
  private
35
35
 
36
+ # @param corrections [String]
36
37
  def log_corrections(corrections)
37
38
  corrections = corrections&.strip
38
39
  return if corrections&.empty?
@@ -51,6 +52,7 @@ module Solargraph
51
52
  conf['rubocop'] || {}
52
53
  end
53
54
 
55
+ # @param config [Hash{String => String}]
54
56
  def cli_args file_uri, config
55
57
  file = UriHelpers.uri_to_file(file_uri)
56
58
  args = [
@@ -68,6 +70,7 @@ module Solargraph
68
70
  args + [file]
69
71
  end
70
72
 
73
+ # @param config [Hash{String => String}]
71
74
  def formatter_class(config)
72
75
  if self.class.const_defined?('BlankRubocopFormatter')
73
76
  # @sg-ignore
@@ -79,6 +82,7 @@ module Solargraph
79
82
  end
80
83
  end
81
84
 
85
+ # @param value [Array, String]
82
86
  def cop_list(value)
83
87
  value = value.join(',') if value.respond_to?(:join)
84
88
  return nil if value == '' || !value.is_a?(String)
@@ -240,7 +240,7 @@ module Solargraph
240
240
  # @param column [Integer]
241
241
  # @param strip [Boolean] Strip special characters from variable names
242
242
  # @param only [Boolean] Search for references in the current file only
243
- # @return [Array<Solargraph::Range>]
243
+ # @return [Array<Solargraph::Location>]
244
244
  # @todo Take a Location instead of filename/line/column
245
245
  def references_from filename, line, column, strip: false, only: false
246
246
  sync_catalog
@@ -398,6 +398,8 @@ module Solargraph
398
398
  return [] unless open?(filename)
399
399
  result = []
400
400
  source = read(filename)
401
+
402
+ # @type [Hash{Class<Solargraph::Diagnostics::Base> => Array<String>}]
401
403
  repargs = {}
402
404
  workspace.config.reporters.each do |line|
403
405
  if line == 'all!'
@@ -650,7 +652,6 @@ module Solargraph
650
652
  return if @sync_count == 0
651
653
 
652
654
  mutex.synchronize do
653
- logger.warn "CATALOG"
654
655
  logger.info "Cataloging #{workspace.directory.empty? ? 'generic workspace' : workspace.directory}"
655
656
  api_map.catalog bench
656
657
  source_map_hash.values.each { |map| find_external_requires(map) }
@@ -5,6 +5,8 @@ module Solargraph
5
5
  # and Range.
6
6
  #
7
7
  class Location
8
+ include Equality
9
+
8
10
  # @return [String]
9
11
  attr_reader :filename
10
12
 
@@ -18,6 +20,11 @@ module Solargraph
18
20
  @range = range
19
21
  end
20
22
 
23
+ # @sg-ignore Fix "Not enough arguments to Module#protected"
24
+ protected def equality_fields
25
+ [filename, range]
26
+ end
27
+
21
28
  # @param location [self]
22
29
  def contain? location
23
30
  range.contain?(location.range.start) && range.contain?(location.range.ending) && filename == location.filename
@@ -74,7 +74,7 @@ module Solargraph
74
74
 
75
75
  # @abstract
76
76
  # @param node [Parser::AST::Node]
77
- # @return [Hash{Parser::AST::Node => Chain}]
77
+ # @return [Hash{Parser::AST::Node => Source::Chain}]
78
78
  def convert_hash node
79
79
  raise NotImplementedError
80
80
  end
@@ -9,6 +9,7 @@ module Solargraph
9
9
  autoload :Base, 'solargraph/parser/node_processor/base'
10
10
 
11
11
  class << self
12
+ # @type [Hash<Symbol, Class<NodeProcessor::Base>>]
12
13
  @@processors ||= {}
13
14
 
14
15
  # Register a processor for a node type.
@@ -94,11 +94,11 @@ module Solargraph
94
94
  elsif n.type == :lvar
95
95
  result.push Chain::Call.new(n.children[0].to_s)
96
96
  elsif n.type == :ivar
97
- result.push Chain::InstanceVariable.new(n.children[0].to_s)
97
+ result.push Chain::InstanceVariable.new(n.children[0].to_s)
98
98
  elsif n.type == :cvar
99
- result.push Chain::ClassVariable.new(n.children[0].to_s)
99
+ result.push Chain::ClassVariable.new(n.children[0].to_s)
100
100
  elsif n.type == :gvar
101
- result.push Chain::GlobalVariable.new(n.children[0].to_s)
101
+ result.push Chain::GlobalVariable.new(n.children[0].to_s)
102
102
  elsif n.type == :or_asgn
103
103
  # @todo: Need a new Link class here that evaluates the
104
104
  # existing variable type with the RHS, and generates a
@@ -12,7 +12,7 @@ require 'ast'
12
12
  # class Node
13
13
  # # New children
14
14
  #
15
- # # @return [Array<AST::Node>]
15
+ # # @return [Array<self>]
16
16
  # attr_reader :children
17
17
  # end
18
18
  # end
@@ -462,7 +462,7 @@ module Solargraph
462
462
  result
463
463
  end
464
464
 
465
- # @param nodes [Enumerable<Parser::AST::Node, BaseObject>]
465
+ # @param nodes [Enumerable<Parser::AST::Node, BasicObject>]
466
466
  # @return [Array<Parser::AST::Node, nil>]
467
467
  def reduce_to_value_nodes nodes
468
468
  result = []
@@ -71,15 +71,14 @@ module Solargraph
71
71
  # @param context_type [ComplexType] The receiver type
72
72
  # @return [self]
73
73
  def resolve_generics definitions, context_type
74
- transformed = transform_types { |t| t.resolve_generics(definitions, context_type) if t }
75
- transformed.erase_generics(definitions.generics)
74
+ transform_types { |t| t.resolve_generics(definitions, context_type) if t }
76
75
  end
77
76
 
78
77
  def all_rooted?
79
78
  !return_type || return_type.all_rooted?
80
79
  end
81
80
 
82
- # @param generics_to_erase [Enumerable<String>]
81
+ # @param generics_to_erase [::Array<String>]
83
82
  # @return [self]
84
83
  def erase_generics(generics_to_erase)
85
84
  return self if generics_to_erase.empty?
@@ -103,7 +102,7 @@ module Solargraph
103
102
  end
104
103
 
105
104
  def to_s
106
- to_rbs
105
+ desc
107
106
  end
108
107
 
109
108
  # @return [Boolean]
@@ -116,14 +115,6 @@ module Solargraph
116
115
  location || type_location
117
116
  end
118
117
 
119
- # Pin equality is determined using the #nearly? method and also
120
- # requiring both pins to have the same location.
121
- #
122
- def == other
123
- return false unless nearly? other
124
- comments == other.comments and location == other.location
125
- end
126
-
127
118
  # True if the specified pin is a near match to this one. A near match
128
119
  # indicates that the pins contain mostly the same data. Any differences
129
120
  # between them should not have an impact on the API surface.
@@ -140,6 +131,14 @@ module Solargraph
140
131
  )
141
132
  end
142
133
 
134
+ # Pin equality is determined using the #nearly? method and also
135
+ # requiring both pins to have the same location.
136
+ #
137
+ def == other
138
+ return false unless nearly? other
139
+ comments == other.comments && location == other.location
140
+ end
141
+
143
142
  # The pin's return type.
144
143
  #
145
144
  # @return [ComplexType]
@@ -266,9 +265,10 @@ module Solargraph
266
265
  result
267
266
  end
268
267
 
268
+ # @deprecated
269
269
  # @return [String]
270
270
  def identity
271
- @identity ||= "#{closure.path}|#{name}"
271
+ @identity ||= "#{closure&.path}|#{name}"
272
272
  end
273
273
 
274
274
  # @return [String, nil]
@@ -276,19 +276,29 @@ module Solargraph
276
276
  return_type.to_rbs
277
277
  end
278
278
 
279
- # @return [String, nil]
280
- def desc
279
+ # @return [String]
280
+ def type_desc
281
+ rbs = to_rbs
282
+ # RBS doesn't have a way to represent a Class<x> type
283
+ rbs = return_type.rooted_tags if return_type.name == 'Class'
281
284
  if path
282
- if to_rbs
283
- path + ' ' + to_rbs
285
+ if rbs
286
+ path + ' ' + rbs
284
287
  else
285
288
  path
286
289
  end
287
290
  else
288
- to_rbs
291
+ rbs
289
292
  end
290
293
  end
291
294
 
295
+ # @return [String]
296
+ def desc
297
+ closure_info = closure&.desc
298
+ binder_info = binder&.desc
299
+ "[#{type_desc}, closure=#{closure_info}, binder=#{binder}"
300
+ end
301
+
292
302
  def inspect
293
303
  "#<#{self.class} `#{self.desc}` at #{self.location.inspect}>"
294
304
  end
@@ -93,6 +93,7 @@ module Solargraph
93
93
  assignment == other.assignment
94
94
  end
95
95
 
96
+ # @param pin [self]
96
97
  def try_merge! pin
97
98
  return false unless super
98
99
  @assignment = pin.assignment
@@ -100,8 +101,8 @@ module Solargraph
100
101
  true
101
102
  end
102
103
 
103
- def desc
104
- "#{to_rbs} = #{assignment&.type.inspect}"
104
+ def type_desc
105
+ "#{super} = #{assignment&.type.inspect}"
105
106
  end
106
107
 
107
108
  private
@@ -36,14 +36,12 @@ module Solargraph
36
36
  #
37
37
  # @return [::Array<ComplexType>]
38
38
  def destructure_yield_types(yield_types, parameters)
39
- return yield_types if yield_types.length == parameters.length
40
-
41
39
  # yielding a tuple into a block will destructure the tuple
42
40
  if yield_types.length == 1
43
41
  yield_type = yield_types.first
44
42
  return yield_type.all_params if yield_type.tuple? && yield_type.all_params.length == parameters.length
45
43
  end
46
- parameters.map { ComplexType::UNDEFINED }
44
+ parameters.map.with_index { |_, idx| yield_types[idx] || ComplexType::UNDEFINED }
47
45
  end
48
46
 
49
47
  # @param api_map [ApiMap]
@@ -3,7 +3,7 @@
3
3
  module Solargraph
4
4
  module Pin
5
5
  class Callable < Closure
6
- # @return [self]
6
+ # @return [Signature]
7
7
  attr_reader :block
8
8
 
9
9
  attr_reader :parameters
@@ -57,7 +57,7 @@ module Solargraph
57
57
  callable
58
58
  end
59
59
 
60
- # @param generics_to_resolve [Enumerable<String>]
60
+ # @param generics_to_resolve [::Array<String>]
61
61
  # @param arg_types [Array<ComplexType>, nil]
62
62
  # @param return_type_context [ComplexType, nil]
63
63
  # @param yield_arg_types [Array<ComplexType>, nil]
@@ -113,7 +113,7 @@ module Solargraph
113
113
  end
114
114
 
115
115
  # @param arguments [::Array<Chain>]
116
- # @param signature [Pin::Signature]
116
+ # @param with_block [Boolean]
117
117
  # @return [Boolean]
118
118
  def arity_matches? arguments, with_block
119
119
  argcount = arguments.length