solargraph 0.54.1 → 0.54.5

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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -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 +68 -121
  6. data/lib/solargraph/api_map.rb +79 -28
  7. data/lib/solargraph/bench.rb +17 -1
  8. data/lib/solargraph/complex_type/type_methods.rb +7 -0
  9. data/lib/solargraph/complex_type/unique_type.rb +21 -1
  10. data/lib/solargraph/complex_type.rb +13 -12
  11. data/lib/solargraph/convention.rb +1 -0
  12. data/lib/solargraph/doc_map.rb +1 -0
  13. data/lib/solargraph/equality.rb +33 -0
  14. data/lib/solargraph/language_server/host/message_worker.rb +23 -6
  15. data/lib/solargraph/language_server/host.rb +12 -11
  16. data/lib/solargraph/language_server/message/base.rb +19 -12
  17. data/lib/solargraph/language_server/message/initialize.rb +3 -1
  18. data/lib/solargraph/language_server/message/text_document/completion.rb +0 -3
  19. data/lib/solargraph/language_server/message/text_document/formatting.rb +4 -0
  20. data/lib/solargraph/library.rb +7 -8
  21. data/lib/solargraph/location.rb +7 -0
  22. data/lib/solargraph/parser/node_methods.rb +1 -1
  23. data/lib/solargraph/parser/node_processor.rb +1 -0
  24. data/lib/solargraph/parser/parser_gem/class_methods.rb +2 -6
  25. data/lib/solargraph/parser/parser_gem/node_chainer.rb +7 -13
  26. data/lib/solargraph/parser/parser_gem/node_methods.rb +2 -2
  27. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +2 -2
  28. data/lib/solargraph/pin/base.rb +28 -18
  29. data/lib/solargraph/pin/base_variable.rb +3 -2
  30. data/lib/solargraph/pin/block.rb +1 -3
  31. data/lib/solargraph/pin/callable.rb +3 -3
  32. data/lib/solargraph/pin/method.rb +6 -0
  33. data/lib/solargraph/pin/namespace.rb +1 -1
  34. data/lib/solargraph/pin/parameter.rb +2 -1
  35. data/lib/solargraph/position.rb +7 -0
  36. data/lib/solargraph/range.rb +7 -0
  37. data/lib/solargraph/rbs_map/conversions.rb +8 -2
  38. data/lib/solargraph/rbs_map.rb +1 -0
  39. data/lib/solargraph/shell.rb +2 -0
  40. data/lib/solargraph/source/chain/array.rb +1 -1
  41. data/lib/solargraph/source/chain/call.rb +15 -8
  42. data/lib/solargraph/source/chain/hash.rb +5 -0
  43. data/lib/solargraph/source/chain/if.rb +5 -0
  44. data/lib/solargraph/source/chain/link.rb +17 -5
  45. data/lib/solargraph/source/chain/literal.rb +5 -0
  46. data/lib/solargraph/source/chain.rb +33 -19
  47. data/lib/solargraph/source/cursor.rb +1 -11
  48. data/lib/solargraph/source.rb +2 -1
  49. data/lib/solargraph/source_map/clip.rb +1 -1
  50. data/lib/solargraph/type_checker.rb +8 -8
  51. data/lib/solargraph/version.rb +1 -1
  52. data/lib/solargraph/workspace/config.rb +7 -3
  53. data/lib/solargraph/workspace.rb +1 -1
  54. data/lib/solargraph/yard_map/mapper/to_constant.rb +1 -0
  55. data/lib/solargraph/yard_map/mapper/to_namespace.rb +1 -0
  56. data/lib/solargraph/yard_map/mapper.rb +1 -0
  57. data/lib/solargraph/yardoc.rb +1 -1
  58. data/lib/solargraph.rb +1 -0
  59. data/solargraph.gemspec +5 -5
  60. metadata +27 -25
@@ -132,6 +132,7 @@ module Solargraph
132
132
  result = false
133
133
  filenames.each do |filename|
134
134
  detach filename
135
+ source_map_hash.delete(filename)
135
136
  result ||= workspace.remove(filename)
136
137
  end
137
138
  result
@@ -192,11 +193,7 @@ module Solargraph
192
193
  else
193
194
  mutex.synchronize do
194
195
  clip = api_map.clip(cursor)
195
- if cursor.assign?
196
- [Pin::ProxyType.new(name: cursor.word, return_type: clip.infer)]
197
- else
198
- clip.define.map { |pin| pin.realize(api_map) }
199
- end
196
+ clip.define.map { |pin| pin.realize(api_map) }
200
197
  end
201
198
  end
202
199
  rescue FileNotFoundError => e
@@ -240,7 +237,7 @@ module Solargraph
240
237
  # @param column [Integer]
241
238
  # @param strip [Boolean] Strip special characters from variable names
242
239
  # @param only [Boolean] Search for references in the current file only
243
- # @return [Array<Solargraph::Range>]
240
+ # @return [Array<Solargraph::Location>]
244
241
  # @todo Take a Location instead of filename/line/column
245
242
  def references_from filename, line, column, strip: false, only: false
246
243
  sync_catalog
@@ -398,6 +395,8 @@ module Solargraph
398
395
  return [] unless open?(filename)
399
396
  result = []
400
397
  source = read(filename)
398
+
399
+ # @type [Hash{Class<Solargraph::Diagnostics::Base> => Array<String>}]
401
400
  repargs = {}
402
401
  workspace.config.reporters.each do |line|
403
402
  if line == 'all!'
@@ -431,7 +430,8 @@ module Solargraph
431
430
  Bench.new(
432
431
  source_maps: source_map_hash.values,
433
432
  workspace: workspace,
434
- external_requires: external_requires
433
+ external_requires: external_requires,
434
+ live_map: @current ? source_map_hash[@current.filename] : nil
435
435
  )
436
436
  end
437
437
 
@@ -650,7 +650,6 @@ module Solargraph
650
650
  return if @sync_count == 0
651
651
 
652
652
  mutex.synchronize do
653
- logger.warn "CATALOG"
654
653
  logger.info "Cataloging #{workspace.directory.empty? ? 'generic workspace' : workspace.directory}"
655
654
  api_map.catalog bench
656
655
  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.
@@ -11,13 +11,9 @@ module Solargraph
11
11
  # @param filename [String, nil]
12
12
  # @return [Array(Parser::AST::Node, Hash{Integer => String})]
13
13
  def parse_with_comments code, filename = nil
14
- buffer = ::Parser::Source::Buffer.new(filename, 0)
15
- buffer.source = code
16
- node = parser.parse(buffer)
14
+ node = parse(code, filename)
17
15
  comments = CommentRipper.new(code, filename, 0).parse
18
16
  [node, comments]
19
- rescue ::Parser::SyntaxError => e
20
- raise Parser::SyntaxError, e.message
21
17
  end
22
18
 
23
19
  # @param code [String]
@@ -28,7 +24,7 @@ module Solargraph
28
24
  buffer = ::Parser::Source::Buffer.new(filename, line)
29
25
  buffer.source = code
30
26
  parser.parse(buffer)
31
- rescue ::Parser::SyntaxError => e
27
+ rescue ::Parser::SyntaxError, ::Parser::UnknownEncodingInMagicComment => e
32
28
  raise Parser::SyntaxError, e.message
33
29
  end
34
30
 
@@ -89,21 +89,15 @@ module Solargraph
89
89
  elsif n.type == :const
90
90
  const = unpack_name(n)
91
91
  result.push Chain::Constant.new(const)
92
- elsif [:lvasgn, :ivasgn, :gvasgn, :cvasgn].include?(n.type)
93
- result.concat generate_links(n.children[1])
94
- elsif n.type == :lvar
92
+ elsif [:lvar, :lvasgn].include?(n.type)
95
93
  result.push Chain::Call.new(n.children[0].to_s)
96
- elsif n.type == :ivar
97
- result.push Chain::InstanceVariable.new(n.children[0].to_s)
98
- elsif n.type == :cvar
99
- result.push Chain::ClassVariable.new(n.children[0].to_s)
100
- elsif n.type == :gvar
101
- result.push Chain::GlobalVariable.new(n.children[0].to_s)
94
+ elsif [:ivar, :ivasgn].include?(n.type)
95
+ result.push Chain::InstanceVariable.new(n.children[0].to_s)
96
+ elsif [:cvar, :cvasgn].include?(n.type)
97
+ result.push Chain::ClassVariable.new(n.children[0].to_s)
98
+ elsif [:gvar, :gvasgn].include?(n.type)
99
+ result.push Chain::GlobalVariable.new(n.children[0].to_s)
102
100
  elsif n.type == :or_asgn
103
- # @todo: Need a new Link class here that evaluates the
104
- # existing variable type with the RHS, and generates a
105
- # union type of the LHS alone if never nil, or minus nil +
106
- # RHS if it is nilable.
107
101
  result.concat generate_links n.children[1]
108
102
  elsif [:class, :module, :def, :defs].include?(n.type)
109
103
  # @todo Undefined or what?
@@ -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 = []
@@ -8,8 +8,8 @@ module Solargraph
8
8
  include ParserGem::NodeMethods
9
9
 
10
10
  def process
11
- # variable not visible until next statement
12
- presence = Range.new(get_node_end_position(node), region.closure.location.range.ending)
11
+ here = get_node_start_position(node)
12
+ presence = Range.new(here, region.closure.location.range.ending)
13
13
  loc = get_node_location(node)
14
14
  locals.push Solargraph::Pin::LocalVariable.new(
15
15
  location: loc,
@@ -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
@@ -31,6 +31,10 @@ module Solargraph
31
31
  @anon_splat = anon_splat
32
32
  end
33
33
 
34
+ def == other
35
+ super && other.node == node
36
+ end
37
+
34
38
  def transform_types(&transform)
35
39
  # @todo 'super' alone should work here I think, but doesn't typecheck at level typed
36
40
  m = super(&transform)
@@ -262,6 +266,7 @@ module Solargraph
262
266
  @attribute
263
267
  end
264
268
 
269
+ # @parm other [Method]
265
270
  def nearly? other
266
271
  super &&
267
272
  parameters == other.parameters &&
@@ -273,6 +278,7 @@ module Solargraph
273
278
  attribute? ? infer_from_iv(api_map) : infer_from_return_nodes(api_map)
274
279
  end
275
280
 
281
+ # @param pin [Pin::Method]
276
282
  def try_merge! pin
277
283
  return false unless super
278
284
  @node = pin.node
@@ -48,7 +48,7 @@ module Solargraph
48
48
  if name.nil? || name.empty?
49
49
  '(top-level)'
50
50
  else
51
- to_rbs
51
+ return_type.rooted_tags
52
52
  end
53
53
  end
54
54
 
@@ -3,7 +3,7 @@
3
3
  module Solargraph
4
4
  module Pin
5
5
  class Parameter < LocalVariable
6
- # @return [Symbol]
6
+ # @return [::Symbol]
7
7
  attr_reader :decl
8
8
 
9
9
  # @return [String]
@@ -121,6 +121,7 @@ module Solargraph
121
121
  tag.text
122
122
  end
123
123
 
124
+ # @param pin [Pin::Parameter]
124
125
  def try_merge! pin
125
126
  return false unless super && closure == pin.closure
126
127
  true
@@ -4,6 +4,8 @@ module Solargraph
4
4
  # The zero-based line and column numbers of a position in a string.
5
5
  #
6
6
  class Position
7
+ include Equality
8
+
7
9
  # @return [Integer]
8
10
  attr_reader :line
9
11
 
@@ -19,6 +21,11 @@ module Solargraph
19
21
  @character = character
20
22
  end
21
23
 
24
+ # @sg-ignore Fix "Not enough arguments to Module#protected"
25
+ protected def equality_fields
26
+ [line, character]
27
+ end
28
+
22
29
  # Get a hash of the position. This representation is suitable for use in
23
30
  # the language server protocol.
24
31
  #
@@ -4,6 +4,8 @@ module Solargraph
4
4
  # A pair of Positions that compose a section of text in code.
5
5
  #
6
6
  class Range
7
+ include Equality
8
+
7
9
  # @return [Position]
8
10
  attr_reader :start
9
11
 
@@ -17,6 +19,11 @@ module Solargraph
17
19
  @ending = ending
18
20
  end
19
21
 
22
+ # @sg-ignore Fix "Not enough arguments to Module#protected"
23
+ protected def equality_fields
24
+ [start, ending]
25
+ end
26
+
20
27
  # Get a hash of the range. This representation is suitable for use in
21
28
  # the language server protocol.
22
29
  #
@@ -80,9 +80,12 @@ module Solargraph
80
80
  # @param closure [Pin::Namespace]
81
81
  # @return [void]
82
82
  def convert_self_type_to_pins decl, closure
83
+ type = build_type(decl.name, decl.args)
84
+ generic_values = type.all_params.map(&:to_s)
83
85
  include_pin = Solargraph::Pin::Reference::Include.new(
84
86
  name: decl.name.relative!.to_s,
85
87
  type_location: location_decl_to_pin_location(decl.location),
88
+ generic_values: generic_values,
86
89
  closure: closure
87
90
  )
88
91
  pins.push include_pin
@@ -318,7 +321,7 @@ module Solargraph
318
321
  # @return [void]
319
322
  def method_def_to_sigs decl, pin
320
323
  decl.overloads.map do |overload|
321
- generics = overload.method_type.type_params.map(&:to_s)
324
+ generics = overload.method_type.type_params.map(&:name).map(&:to_s)
322
325
  signature_parameters, signature_return_type = parts_of_function(overload.method_type, pin)
323
326
  block = if overload.method_type.block
324
327
  block_parameters, block_return_type = parts_of_function(overload.method_type.block, pin)
@@ -628,9 +631,12 @@ module Solargraph
628
631
  def add_mixins decl, namespace
629
632
  decl.each_mixin do |mixin|
630
633
  klass = mixin.is_a?(RBS::AST::Members::Include) ? Pin::Reference::Include : Pin::Reference::Extend
634
+ type = build_type(mixin.name, mixin.args)
635
+ generic_values = type.all_params.map(&:to_s)
631
636
  pins.push klass.new(
632
637
  name: mixin.name.relative!.to_s,
633
- location: location_decl_to_pin_location(mixin.location),
638
+ type_location: location_decl_to_pin_location(mixin.location),
639
+ generic_values: generic_values,
634
640
  closure: namespace
635
641
  )
636
642
  end
@@ -64,6 +64,7 @@ module Solargraph
64
64
  @@rbs_maps_hash[library] ||= RbsMap.new(library)
65
65
  end
66
66
 
67
+ # @param gemspec [Gem::Specification]
67
68
  def self.from_gemspec(gemspec)
68
69
  RbsMap.new(gemspec.name, gemspec.version)
69
70
  end
@@ -111,6 +111,7 @@ module Solargraph
111
111
  also be specified to clear cached system documentation.
112
112
  Documentation will be regenerated as needed.
113
113
  )
114
+ # @param gems [Array<String>]
114
115
  # @return [void]
115
116
  def uncache *gems
116
117
  raise ArgumentError, 'No gems specified.' if gems.empty?
@@ -133,6 +134,7 @@ module Solargraph
133
134
 
134
135
  desc 'gems [GEM[=VERSION]]', 'Cache documentation for installed gems'
135
136
  option :rebuild, type: :boolean, desc: 'Rebuild existing documentation', default: false
137
+ # @param names [Array<String>]
136
138
  # @return [void]
137
139
  def gems *names
138
140
  if names.empty?
@@ -14,7 +14,7 @@ module Solargraph
14
14
 
15
15
  # @param api_map [ApiMap]
16
16
  # @param name_pin [Pin::Base]
17
- # @param locals [Enumerable<Pin::LocalVariable>]
17
+ # @param locals [::Array<Pin::Parameter, Pin::LocalVariable>]
18
18
  def resolve api_map, name_pin, locals
19
19
  child_types = @children.map do |child|
20
20
  child.infer(api_map, name_pin, locals)
@@ -25,6 +25,11 @@ module Solargraph
25
25
  fix_block_pass
26
26
  end
27
27
 
28
+ # @sg-ignore Fix "Not enough arguments to Module#protected"
29
+ protected def equality_fields
30
+ super + [arguments, block]
31
+ end
32
+
28
33
  def with_block?
29
34
  !!@block
30
35
  end
@@ -42,8 +47,8 @@ module Solargraph
42
47
  end
43
48
  return inferred_pins(found, api_map, name_pin, locals) unless found.empty?
44
49
  pins = name_pin.binder.each_unique_type.flat_map do |context|
45
- method_context = context.namespace == '' ? '' : context.tag
46
- api_map.get_method_stack(method_context, word, scope: context.scope)
50
+ ns = context.namespace == '' ? '' : context.namespace_type.tag
51
+ api_map.get_method_stack(ns, word, scope: context.scope)
47
52
  end
48
53
  return [] if pins.empty?
49
54
  inferred_pins(pins, api_map, name_pin, locals)
@@ -54,7 +59,7 @@ module Solargraph
54
59
  # @param pins [::Enumerable<Pin::Method>]
55
60
  # @param api_map [ApiMap]
56
61
  # @param name_pin [Pin::Base]
57
- # @param locals [::Array<Pin::LocalVariable>]
62
+ # @param locals [::Array<Solargraph::Pin::LocalVariable, Solargraph::Pin::Parameter>]
58
63
  # @return [::Array<Pin::Base>]
59
64
  def inferred_pins pins, api_map, name_pin, locals
60
65
  result = pins.map do |p|
@@ -81,10 +86,12 @@ module Solargraph
81
86
  break
82
87
  end
83
88
  atype = atypes[idx] ||= arg.infer(api_map, Pin::ProxyType.anonymous(name_pin.context), locals)
84
- ptype = param.return_type
89
+ # make sure we get types from up the method
90
+ # inheritance chain if we don't have them on this pin
91
+ ptype = param.typify api_map
85
92
  # @todo Weak type comparison
86
93
  # unless atype.tag == param.return_type.tag || api_map.super_and_sub?(param.return_type.tag, atype.tag)
87
- unless param.return_type.undefined? || atype.name == param.return_type.name || api_map.super_and_sub?(param.return_type.name, atype.name) || param.return_type.generic?
94
+ unless ptype.undefined? || atype.name == ptype.name || ptype.any? { |current_ptype| api_map.super_and_sub?(current_ptype.name, atype.name) } || ptype.generic? || param.restarg?
88
95
  match = false
89
96
  break
90
97
  end
@@ -132,7 +139,7 @@ module Solargraph
132
139
  # @param pin [Pin::Base]
133
140
  # @param api_map [ApiMap]
134
141
  # @param context [ComplexType]
135
- # @param locals [Enumerable<Pin::Base>]
142
+ # @param locals [::Array<Solargraph::Pin::LocalVariable, Solargraph::Pin::Parameter>]
136
143
  # @return [Pin::Base]
137
144
  def process_macro pin, api_map, context, locals
138
145
  pin.macros.each do |macro|
@@ -151,7 +158,7 @@ module Solargraph
151
158
  # @param pin [Pin::Method]
152
159
  # @param api_map [ApiMap]
153
160
  # @param context [ComplexType]
154
- # @param locals [Enumerable<Pin::Base>]
161
+ # @param locals [::Array<Solargraph::Pin::LocalVariable, Solargraph::Pin::Parameter>]
155
162
  # @return [Pin::ProxyType]
156
163
  def process_directive pin, api_map, context, locals
157
164
  pin.directives.each do |dir|
@@ -167,7 +174,7 @@ module Solargraph
167
174
  # @param macro [YARD::Tags::MacroDirective]
168
175
  # @param api_map [ApiMap]
169
176
  # @param context [ComplexType]
170
- # @param locals [Enumerable<Pin::Base>]
177
+ # @param locals [::Array<Pin::LocalVariable, Pin::Parameter>]
171
178
  # @return [Pin::ProxyType]
172
179
  def inner_process_macro pin, macro, api_map, context, locals
173
180
  vals = arguments.map{ |c| Pin::ProxyType.anonymous(c.infer(api_map, pin, locals)) }
@@ -11,6 +11,11 @@ module Solargraph
11
11
  @splatted = splatted
12
12
  end
13
13
 
14
+ # @sg-ignore Fix "Not enough arguments to Module#protected"
15
+ protected def equality_fields
16
+ super + [@splatted]
17
+ end
18
+
14
19
  def word
15
20
  @word ||= "<#{@type}>"
16
21
  end
@@ -13,6 +13,11 @@ module Solargraph
13
13
  @links = links
14
14
  end
15
15
 
16
+ # @sg-ignore Fix "Not enough arguments to Module#protected"
17
+ protected def equality_fields
18
+ super + [@links]
19
+ end
20
+
16
21
  def resolve api_map, name_pin, locals
17
22
  types = @links.map { |link| link.infer(api_map, name_pin, locals) }
18
23
  [Solargraph::Pin::ProxyType.anonymous(Solargraph::ComplexType.try_parse(types.map(&:tag).uniq.join(', ')))]
@@ -4,6 +4,8 @@ module Solargraph
4
4
  class Source
5
5
  class Chain
6
6
  class Link
7
+ include Equality
8
+
7
9
  # @return [String]
8
10
  attr_reader :word
9
11
 
@@ -15,6 +17,11 @@ module Solargraph
15
17
  @word = word
16
18
  end
17
19
 
20
+ # @sg-ignore Fix "Not enough arguments to Module#protected"
21
+ protected def equality_fields
22
+ [self.class, word]
23
+ end
24
+
18
25
  def undefined?
19
26
  word == '<undefined>'
20
27
  end
@@ -31,18 +38,23 @@ module Solargraph
31
38
  []
32
39
  end
33
40
 
41
+ # debugging description of contents; not for machine use
42
+ def desc
43
+ word
44
+ end
45
+
46
+ def to_s
47
+ desc
48
+ end
49
+
34
50
  def inspect
35
- "#{self.class} #{word}"
51
+ "#<#{self.class} - `#{self.desc}`>"
36
52
  end
37
53
 
38
54
  def head?
39
55
  @head ||= false
40
56
  end
41
57
 
42
- def == other
43
- self.class == other.class and word == other.word
44
- end
45
-
46
58
  # Make a copy of this link marked as the head of a chain
47
59
  #
48
60
  # @return [self]