solargraph 0.54.1 → 0.55.0

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 (85) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +39 -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 +71 -122
  6. data/lib/solargraph/api_map.rb +97 -36
  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 +109 -8
  10. data/lib/solargraph/complex_type.rb +48 -18
  11. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +51 -0
  12. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +100 -0
  13. data/lib/solargraph/convention/struct_definition.rb +101 -0
  14. data/lib/solargraph/convention.rb +2 -0
  15. data/lib/solargraph/doc_map.rb +43 -18
  16. data/lib/solargraph/equality.rb +33 -0
  17. data/lib/solargraph/language_server/host/message_worker.rb +31 -11
  18. data/lib/solargraph/language_server/host.rb +13 -11
  19. data/lib/solargraph/language_server/message/base.rb +19 -12
  20. data/lib/solargraph/language_server/message/initialize.rb +3 -1
  21. data/lib/solargraph/language_server/message/text_document/completion.rb +0 -3
  22. data/lib/solargraph/language_server/message/text_document/formatting.rb +4 -0
  23. data/lib/solargraph/library.rb +7 -8
  24. data/lib/solargraph/location.rb +15 -0
  25. data/lib/solargraph/parser/comment_ripper.rb +11 -6
  26. data/lib/solargraph/parser/flow_sensitive_typing.rb +226 -0
  27. data/lib/solargraph/parser/node_methods.rb +15 -1
  28. data/lib/solargraph/parser/parser_gem/class_methods.rb +11 -6
  29. data/lib/solargraph/parser/parser_gem/node_chainer.rb +17 -23
  30. data/lib/solargraph/parser/parser_gem/node_methods.rb +5 -3
  31. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +21 -0
  32. data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +21 -1
  33. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +21 -0
  34. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +2 -2
  35. data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +26 -5
  36. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +41 -0
  37. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +28 -0
  38. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +28 -0
  39. data/lib/solargraph/parser/parser_gem/node_processors.rb +10 -0
  40. data/lib/solargraph/parser.rb +1 -0
  41. data/lib/solargraph/pin/base.rb +35 -19
  42. data/lib/solargraph/pin/base_variable.rb +10 -3
  43. data/lib/solargraph/pin/block.rb +3 -3
  44. data/lib/solargraph/pin/breakable.rb +9 -0
  45. data/lib/solargraph/pin/callable.rb +3 -3
  46. data/lib/solargraph/pin/local_variable.rb +7 -1
  47. data/lib/solargraph/pin/method.rb +26 -18
  48. data/lib/solargraph/pin/namespace.rb +10 -7
  49. data/lib/solargraph/pin/parameter.rb +15 -6
  50. data/lib/solargraph/pin/proxy_type.rb +12 -6
  51. data/lib/solargraph/pin/until.rb +18 -0
  52. data/lib/solargraph/pin/while.rb +18 -0
  53. data/lib/solargraph/pin.rb +3 -0
  54. data/lib/solargraph/position.rb +7 -0
  55. data/lib/solargraph/range.rb +7 -0
  56. data/lib/solargraph/rbs_map/conversions.rb +16 -10
  57. data/lib/solargraph/rbs_map/core_fills.rb +10 -3
  58. data/lib/solargraph/rbs_map.rb +1 -0
  59. data/lib/solargraph/shell.rb +2 -0
  60. data/lib/solargraph/source/chain/array.rb +5 -4
  61. data/lib/solargraph/source/chain/call.rb +55 -19
  62. data/lib/solargraph/source/chain/constant.rb +1 -1
  63. data/lib/solargraph/source/chain/hash.rb +8 -2
  64. data/lib/solargraph/source/chain/if.rb +5 -0
  65. data/lib/solargraph/source/chain/link.rb +19 -5
  66. data/lib/solargraph/source/chain/literal.rb +27 -2
  67. data/lib/solargraph/source/chain/z_super.rb +1 -1
  68. data/lib/solargraph/source/chain.rb +107 -63
  69. data/lib/solargraph/source/cursor.rb +1 -11
  70. data/lib/solargraph/source/source_chainer.rb +2 -2
  71. data/lib/solargraph/source.rb +2 -1
  72. data/lib/solargraph/source_map/clip.rb +4 -2
  73. data/lib/solargraph/type_checker/checks.rb +4 -0
  74. data/lib/solargraph/type_checker.rb +41 -14
  75. data/lib/solargraph/version.rb +1 -1
  76. data/lib/solargraph/workspace/config.rb +7 -3
  77. data/lib/solargraph/workspace.rb +1 -1
  78. data/lib/solargraph/yard_map/mapper/to_constant.rb +1 -0
  79. data/lib/solargraph/yard_map/mapper/to_method.rb +42 -15
  80. data/lib/solargraph/yard_map/mapper/to_namespace.rb +1 -0
  81. data/lib/solargraph/yard_map/mapper.rb +1 -0
  82. data/lib/solargraph/yardoc.rb +1 -1
  83. data/lib/solargraph.rb +1 -0
  84. data/solargraph.gemspec +5 -5
  85. metadata +39 -25
@@ -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]
@@ -11,12 +11,10 @@ module Solargraph
11
11
 
12
12
  # @param decl [::Symbol] :arg, :optarg, :kwarg, :kwoptarg, :restarg, :kwrestarg, :block, :blockarg
13
13
  # @param asgn_code [String, nil]
14
- # @param return_type [ComplexType, nil]
15
- def initialize decl: :arg, asgn_code: nil, return_type: nil, **splat
14
+ def initialize decl: :arg, asgn_code: nil, **splat
16
15
  super(**splat)
17
16
  @asgn_code = asgn_code
18
17
  @decl = decl
19
- @return_type = return_type
20
18
  end
21
19
 
22
20
  def keyword?
@@ -115,12 +113,22 @@ module Solargraph
115
113
  closure.is_a?(Pin::Block) ? typify_block_param(api_map) : typify_method_param(api_map)
116
114
  end
117
115
 
116
+ # @param atype [ComplexType]
117
+ # @param api_map [ApiMap]
118
+ def compatible_arg?(atype, api_map)
119
+ # make sure we get types from up the method
120
+ # inheritance chain if we don't have them on this pin
121
+ ptype = typify api_map
122
+ ptype.undefined? || ptype.can_assign?(api_map, atype) || ptype.generic?
123
+ end
124
+
118
125
  def documentation
119
126
  tag = param_tag
120
127
  return '' if tag.nil? || tag.text.nil?
121
128
  tag.text
122
129
  end
123
130
 
131
+ # @param pin [Pin::Parameter]
124
132
  def try_merge! pin
125
133
  return false unless super && closure == pin.closure
126
134
  true
@@ -140,8 +148,9 @@ module Solargraph
140
148
  # @param api_map [ApiMap]
141
149
  # @return [ComplexType]
142
150
  def typify_block_param api_map
143
- if closure.is_a?(Pin::Block) && closure.receiver
144
- return closure.typify_parameters(api_map)[index]
151
+ block_pin = closure
152
+ if block_pin.is_a?(Pin::Block) && block_pin.receiver
153
+ return block_pin.typify_parameters(api_map)[index]
145
154
  end
146
155
  ComplexType::UNDEFINED
147
156
  end
@@ -4,24 +4,30 @@ module Solargraph
4
4
  module Pin
5
5
  class ProxyType < Base
6
6
  # @param return_type [ComplexType]
7
- def initialize return_type: ComplexType::UNDEFINED, **splat
7
+ def initialize return_type: ComplexType::UNDEFINED, binder: nil, **splat
8
8
  super(**splat)
9
9
  @return_type = return_type
10
+ @binder = binder if binder
10
11
  end
11
12
 
12
13
  def context
13
14
  @return_type
14
15
  end
15
16
 
16
- # @param return_type [ComplexType]
17
+ # @param context [ComplexType, ComplexType::UniqueType] Used as context for this pin
18
+ # @param closure [Pin::Namespace, nil] Used as the closure for this pin
19
+ # @param binder [ComplexType, ComplexType::UniqueType, nil]
17
20
  # @return [ProxyType]
18
- def self.anonymous return_type
19
- parts = return_type.namespace.split('::')
20
- namespace = parts[0..-2].join('::').to_s
21
+ def self.anonymous context, closure: nil, binder: nil
22
+ unless closure
23
+ parts = context.namespace.split('::')
24
+ namespace = parts[0..-2].join('::').to_s
25
+ closure = Solargraph::Pin::Namespace.new(name: namespace)
26
+ end
21
27
  # name = parts.last.to_s
22
28
  # ProxyType.new(nil, namespace, name, return_type)
23
29
  ProxyType.new(
24
- closure: Solargraph::Pin::Namespace.new(name: namespace), return_type: return_type
30
+ closure: closure, return_type: context, binder: binder || context
25
31
  )
26
32
  end
27
33
  end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Pin
5
+ class Until < Base
6
+ include Breakable
7
+
8
+ # @param receiver [Parser::AST::Node, nil]
9
+ # @param node [Parser::AST::Node, nil]
10
+ # @param context [ComplexType, nil]
11
+ # @param args [::Array<Parameter>]
12
+ def initialize node: nil, **splat
13
+ super(**splat)
14
+ @node = node
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Pin
5
+ class While < Base
6
+ include Breakable
7
+
8
+ # @param receiver [Parser::AST::Node, nil]
9
+ # @param node [Parser::AST::Node, nil]
10
+ # @param context [ComplexType, nil]
11
+ # @param args [::Array<Parameter>]
12
+ def initialize node: nil, **splat
13
+ super(**splat)
14
+ @node = node
15
+ end
16
+ end
17
+ end
18
+ end
@@ -34,6 +34,9 @@ module Solargraph
34
34
  autoload :Singleton, 'solargraph/pin/singleton'
35
35
  autoload :KeywordParam, 'solargraph/pin/keyword_param'
36
36
  autoload :Search, 'solargraph/pin/search'
37
+ autoload :Breakable, 'solargraph/pin/breakable'
38
+ autoload :Until, 'solargraph/pin/until'
39
+ autoload :While, 'solargraph/pin/while'
37
40
  autoload :Callable, 'solargraph/pin/callable'
38
41
 
39
42
  ROOT_PIN = Pin::Namespace.new(type: :class, name: '', closure: nil)
@@ -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)
@@ -348,34 +351,34 @@ module Solargraph
348
351
  parameters = []
349
352
  arg_num = -1
350
353
  type.type.required_positionals.each do |param|
351
- name = param.name ? param.name.to_s : "arg#{arg_num += 1}"
354
+ name = param.name ? param.name.to_s : "arg_#{arg_num += 1}"
352
355
  parameters.push Solargraph::Pin::Parameter.new(decl: :arg, name: name, closure: pin, return_type: ComplexType.try_parse(other_type_to_tag(param.type)).force_rooted)
353
356
  end
354
357
  type.type.optional_positionals.each do |param|
355
- name = param.name ? param.name.to_s : "arg#{arg_num += 1}"
358
+ name = param.name ? param.name.to_s : "arg_#{arg_num += 1}"
356
359
  parameters.push Solargraph::Pin::Parameter.new(decl: :optarg, name: name, closure: pin,
357
360
  return_type: ComplexType.try_parse(other_type_to_tag(param.type)).force_rooted)
358
361
  end
359
362
  if type.type.rest_positionals
360
- name = type.type.rest_positionals.name ? type.type.rest_positionals.name.to_s : "arg#{arg_num += 1}"
363
+ name = type.type.rest_positionals.name ? type.type.rest_positionals.name.to_s : "arg_#{arg_num += 1}"
361
364
  parameters.push Solargraph::Pin::Parameter.new(decl: :restarg, name: name, closure: pin)
362
365
  end
363
366
  type.type.trailing_positionals.each do |param|
364
- name = param.name ? param.name.to_s : "arg#{arg_num += 1}"
367
+ name = param.name ? param.name.to_s : "arg_#{arg_num += 1}"
365
368
  parameters.push Solargraph::Pin::Parameter.new(decl: :arg, name: name, closure: pin)
366
369
  end
367
370
  type.type.required_keywords.each do |orig, param|
368
- name = orig ? orig.to_s : "arg#{arg_num += 1}"
371
+ name = orig ? orig.to_s : "arg_#{arg_num += 1}"
369
372
  parameters.push Solargraph::Pin::Parameter.new(decl: :kwarg, name: name, closure: pin,
370
373
  return_type: ComplexType.try_parse(other_type_to_tag(param.type)).force_rooted)
371
374
  end
372
375
  type.type.optional_keywords.each do |orig, param|
373
- name = orig ? orig.to_s : "arg#{arg_num += 1}"
376
+ name = orig ? orig.to_s : "arg_#{arg_num += 1}"
374
377
  parameters.push Solargraph::Pin::Parameter.new(decl: :kwoptarg, name: name, closure: pin,
375
378
  return_type: ComplexType.try_parse(other_type_to_tag(param.type)).force_rooted)
376
379
  end
377
380
  if type.type.rest_keywords
378
- name = type.type.rest_keywords.name ? type.type.rest_keywords.name.to_s : "arg#{arg_num += 1}"
381
+ name = type.type.rest_keywords.name ? type.type.rest_keywords.name.to_s : "arg_#{arg_num += 1}"
379
382
  parameters.push Solargraph::Pin::Parameter.new(decl: :kwrestarg, name: type.type.rest_keywords.name.to_s, closure: pin)
380
383
  end
381
384
 
@@ -572,7 +575,7 @@ module Solargraph
572
575
  elsif type.is_a?(RBS::Types::Tuple)
573
576
  "Array(#{type.types.map { |t| other_type_to_tag(t) }.join(', ')})"
574
577
  elsif type.is_a?(RBS::Types::Literal)
575
- type.literal.to_s
578
+ type.literal.inspect
576
579
  elsif type.is_a?(RBS::Types::Union)
577
580
  type.types.map { |t| other_type_to_tag(t) }.join(', ')
578
581
  elsif type.is_a?(RBS::Types::Record)
@@ -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
@@ -16,8 +16,6 @@ module Solargraph
16
16
  ].map { |k| Pin::Keyword.new(k) }
17
17
 
18
18
  MISSING = [
19
- Solargraph::Pin::Method.new(name: 'tap', scope: :instance,
20
- closure: Solargraph::Pin::Namespace.new(name: 'Object')),
21
19
  Solargraph::Pin::Method.new(name: 'class', scope: :instance,
22
20
  closure: Solargraph::Pin::Namespace.new(name: 'Object'), comments: '@return [::Class<self>]')
23
21
  ]
@@ -35,6 +33,15 @@ module Solargraph
35
33
  Override.method_return('Class#allocate', 'self')
36
34
  ]
37
35
 
36
+ # @todo I don't see any direct link in RBS to build this from -
37
+ # presumably RBS is using duck typing to match interfaces
38
+ # against concrete classes
39
+ INCLUDES = [
40
+ Solargraph::Pin::Reference::Include.new(name: '_ToAry',
41
+ closure: Solargraph::Pin::Namespace.new(name: 'Array'),
42
+ generic_values: ['generic<Elem>'])
43
+ ]
44
+
38
45
  # HACK: Add Errno exception classes
39
46
  errno = Solargraph::Pin::Namespace.new(name: 'Errno')
40
47
  errnos = []
@@ -44,7 +51,7 @@ module Solargraph
44
51
  end
45
52
  ERRNOS = errnos
46
53
 
47
- ALL = KEYWORDS + MISSING + OVERRIDES + ERRNOS
54
+ ALL = KEYWORDS + MISSING + OVERRIDES + ERRNOS + INCLUDES
48
55
  end
49
56
  end
50
57
  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?
@@ -3,8 +3,9 @@ module Solargraph
3
3
  class Chain
4
4
  class Array < Literal
5
5
  # @param children [::Array<Chain>]
6
- def initialize children
7
- super('::Array')
6
+ # @param node [Parser::AST::Node]
7
+ def initialize children, node
8
+ super('::Array', node)
8
9
  @children = children
9
10
  end
10
11
 
@@ -14,10 +15,10 @@ module Solargraph
14
15
 
15
16
  # @param api_map [ApiMap]
16
17
  # @param name_pin [Pin::Base]
17
- # @param locals [Enumerable<Pin::LocalVariable>]
18
+ # @param locals [::Array<Pin::Parameter, Pin::LocalVariable>]
18
19
  def resolve api_map, name_pin, locals
19
20
  child_types = @children.map do |child|
20
- child.infer(api_map, name_pin, locals)
21
+ child.infer(api_map, name_pin, locals).simplify_literals
21
22
  end
22
23
 
23
24
  type = if child_types.uniq.length == 1 && child_types.first.defined?
@@ -3,12 +3,20 @@
3
3
  module Solargraph
4
4
  class Source
5
5
  class Chain
6
+ #
7
+ # Handles both method calls and local variable references by
8
+ # first looking for a variable with the name 'word', then
9
+ # proceeding to method signature resolution if not found.
10
+ #
6
11
  class Call < Chain::Link
7
12
  include Solargraph::Parser::NodeMethods
8
13
 
9
14
  # @return [String]
10
15
  attr_reader :word
11
16
 
17
+ # @return [Location]
18
+ attr_reader :location
19
+
12
20
  # @return [::Array<Chain>]
13
21
  attr_reader :arguments
14
22
 
@@ -16,34 +24,42 @@ module Solargraph
16
24
  attr_reader :block
17
25
 
18
26
  # @param word [String]
27
+ # @param location [Location, nil]
19
28
  # @param arguments [::Array<Chain>]
20
29
  # @param block [Chain, nil]
21
- def initialize word, arguments = [], block = nil
30
+ def initialize word, location = nil, arguments = [], block = nil
22
31
  @word = word
32
+ @location = location
23
33
  @arguments = arguments
24
34
  @block = block
25
35
  fix_block_pass
26
36
  end
27
37
 
38
+ # @sg-ignore Fix "Not enough arguments to Module#protected"
39
+ protected def equality_fields
40
+ super + [arguments, block]
41
+ end
42
+
28
43
  def with_block?
29
44
  !!@block
30
45
  end
31
46
 
32
47
  # @param api_map [ApiMap]
33
- # @param name_pin [Pin::Closure] name_pin.binder should give us the object on which 'word' will be invoked
48
+ # @param name_pin [Pin::Closure] name_pin.binder should give us the type of the object on which 'word' will be invoked
34
49
  # @param locals [::Array<Pin::LocalVariable>]
35
50
  def resolve api_map, name_pin, locals
36
51
  return super_pins(api_map, name_pin) if word == 'super'
37
52
  return yield_pins(api_map, name_pin) if word == 'yield'
38
53
  found = if head?
39
- locals.select { |p| p.name == word }
54
+ api_map.visible_pins(locals, word, name_pin, location)
40
55
  else
41
56
  []
42
57
  end
43
58
  return inferred_pins(found, api_map, name_pin, locals) unless found.empty?
44
59
  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)
60
+ ns_tag = context.namespace == '' ? '' : context.namespace_type.tag
61
+ stack = api_map.get_method_stack(ns_tag, word, scope: context.scope)
62
+ [stack.first].compact
47
63
  end
48
64
  return [] if pins.empty?
49
65
  inferred_pins(pins, api_map, name_pin, locals)
@@ -54,7 +70,7 @@ module Solargraph
54
70
  # @param pins [::Enumerable<Pin::Method>]
55
71
  # @param api_map [ApiMap]
56
72
  # @param name_pin [Pin::Base]
57
- # @param locals [::Array<Pin::LocalVariable>]
73
+ # @param locals [::Array<Solargraph::Pin::LocalVariable, Solargraph::Pin::Parameter>]
58
74
  # @return [::Array<Pin::Base>]
59
75
  def inferred_pins pins, api_map, name_pin, locals
60
76
  result = pins.map do |p|
@@ -67,7 +83,8 @@ module Solargraph
67
83
  # use it. If we didn't pass a block, the logic below will
68
84
  # reject it regardless
69
85
 
70
- sorted_overloads = overloads.sort { |ol| ol.block? ? -1 : 1 }
86
+ with_block, without_block = overloads.partition(&:block?)
87
+ sorted_overloads = with_block + without_block
71
88
  new_signature_pin = nil
72
89
  sorted_overloads.each do |ol|
73
90
  next unless ol.arity_matches?(arguments, with_block?)
@@ -80,11 +97,9 @@ module Solargraph
80
97
  match = ol.parameters.any?(&:restarg?)
81
98
  break
82
99
  end
100
+
83
101
  atype = atypes[idx] ||= arg.infer(api_map, Pin::ProxyType.anonymous(name_pin.context), locals)
84
- ptype = param.return_type
85
- # @todo Weak type comparison
86
- # 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?
102
+ unless param.compatible_arg?(atype, api_map) || param.restarg?
88
103
  match = false
89
104
  break
90
105
  end
@@ -101,7 +116,27 @@ module Solargraph
101
116
  end
102
117
  new_signature_pin = ol.resolve_generics_from_context_until_complete(ol.generics, atypes, nil, nil, blocktype)
103
118
  new_return_type = new_signature_pin.return_type
104
- type = with_params(new_return_type.self_to_type(name_pin.context), name_pin.context).qualify(api_map, name_pin.context.namespace) if new_return_type.defined?
119
+ if head?
120
+ # If we're at the head of the chain, we called a
121
+ # method somewhere that marked itself as returning
122
+ # self. Given we didn't invoke this on an object,
123
+ # this must be a method in this same class - so we
124
+ # use our own self type
125
+ self_type = name_pin.context
126
+ else
127
+ # if we're past the head in the chain, whatever the
128
+ # type of the lhs side is what 'self' will be in its
129
+ # declaration - we can't just use the type of the
130
+ # method pin, as this might be a subclass of the
131
+ # place where the method is defined
132
+ self_type = name_pin.binder
133
+ end
134
+ # This same logic applies to the YARD work done by
135
+ # 'with_params()'.
136
+ #
137
+ # qualify(), however, happens in the namespace where
138
+ # the docs were written - from the method pin.
139
+ type = with_params(new_return_type.self_to_type(self_type), self_type).qualify(api_map, p.namespace) if new_return_type.defined?
105
140
  type ||= ComplexType::UNDEFINED
106
141
  end
107
142
  break if type.defined?
@@ -117,13 +152,14 @@ module Solargraph
117
152
  end
118
153
  p
119
154
  end
120
- result.map do |pin|
121
- if pin.path == 'Class#new' && name_pin.context.tag != 'Class'
122
- reduced_context = name_pin.context.reduce_class_type
155
+ logger.debug { "Call#inferred_pins(name_pin.binder=#{name_pin.binder}, word=#{word}, pins=#{pins.map(&:desc)}, name_pin=#{name_pin}) - result=#{result}" }
156
+ out = result.map do |pin|
157
+ if pin.path == 'Class#new' && name_pin.binder.tag != 'Class'
158
+ reduced_context = name_pin.binder.reduce_class_type
123
159
  pin.proxy(reduced_context)
124
160
  else
125
161
  next pin if pin.return_type.undefined?
126
- selfy = pin.return_type.self_to_type(name_pin.context)
162
+ selfy = pin.return_type.self_to_type(name_pin.binder)
127
163
  selfy == pin.return_type ? pin : pin.proxy(selfy)
128
164
  end
129
165
  end
@@ -132,7 +168,7 @@ module Solargraph
132
168
  # @param pin [Pin::Base]
133
169
  # @param api_map [ApiMap]
134
170
  # @param context [ComplexType]
135
- # @param locals [Enumerable<Pin::Base>]
171
+ # @param locals [::Array<Solargraph::Pin::LocalVariable, Solargraph::Pin::Parameter>]
136
172
  # @return [Pin::Base]
137
173
  def process_macro pin, api_map, context, locals
138
174
  pin.macros.each do |macro|
@@ -151,7 +187,7 @@ module Solargraph
151
187
  # @param pin [Pin::Method]
152
188
  # @param api_map [ApiMap]
153
189
  # @param context [ComplexType]
154
- # @param locals [Enumerable<Pin::Base>]
190
+ # @param locals [::Array<Solargraph::Pin::LocalVariable, Solargraph::Pin::Parameter>]
155
191
  # @return [Pin::ProxyType]
156
192
  def process_directive pin, api_map, context, locals
157
193
  pin.directives.each do |dir|
@@ -167,7 +203,7 @@ module Solargraph
167
203
  # @param macro [YARD::Tags::MacroDirective]
168
204
  # @param api_map [ApiMap]
169
205
  # @param context [ComplexType]
170
- # @param locals [Enumerable<Pin::Base>]
206
+ # @param locals [::Array<Pin::LocalVariable, Pin::Parameter>]
171
207
  # @return [Pin::ProxyType]
172
208
  def inner_process_macro pin, macro, api_map, context, locals
173
209
  vals = arguments.map{ |c| Pin::ProxyType.anonymous(c.infer(api_map, pin, locals)) }
@@ -41,7 +41,7 @@ module Solargraph
41
41
 
42
42
  private
43
43
 
44
- # @param pin [Pin::Base]
44
+ # @param pin [Pin::Closure]
45
45
  # @return [::Array<String>]
46
46
  def crawl_gates pin
47
47
  clos = pin
@@ -5,12 +5,18 @@ module Solargraph
5
5
  class Chain
6
6
  class Hash < Literal
7
7
  # @param type [String]
8
+ # @param node [Parser::AST::Node]
8
9
  # @param splatted [Boolean]
9
- def initialize type, splatted = false
10
- super(type)
10
+ def initialize type, node, splatted = false
11
+ super(type, node)
11
12
  @splatted = splatted
12
13
  end
13
14
 
15
+ # @sg-ignore Fix "Not enough arguments to Module#protected"
16
+ protected def equality_fields
17
+ super + [@splatted]
18
+ end
19
+
14
20
  def word
15
21
  @word ||= "<#{@type}>"
16
22
  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]
@@ -70,6 +82,8 @@ module Solargraph
70
82
  "#<#{self.class} - `#{self.desc}`>"
71
83
  end
72
84
 
85
+ include Logging
86
+
73
87
  protected
74
88
 
75
89
  # Mark whether this link is the head of a chain