solargraph 0.51.2 → 0.52.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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +2 -2
  3. data/CHANGELOG.md +25 -5
  4. data/lib/solargraph/api_map/cache.rb +2 -0
  5. data/lib/solargraph/api_map/store.rb +2 -2
  6. data/lib/solargraph/api_map.rb +11 -4
  7. data/lib/solargraph/complex_type/type_methods.rb +1 -1
  8. data/lib/solargraph/complex_type/unique_type.rb +20 -13
  9. data/lib/solargraph/complex_type.rb +13 -9
  10. data/lib/solargraph/documentor.rb +1 -1
  11. data/lib/solargraph/library.rb +12 -5
  12. data/lib/solargraph/parser/comment_ripper.rb +1 -0
  13. data/lib/solargraph/parser/legacy/class_methods.rb +2 -2
  14. data/lib/solargraph/parser/legacy/node_chainer.rb +9 -4
  15. data/lib/solargraph/parser/legacy/node_methods.rb +5 -3
  16. data/lib/solargraph/parser/node_methods.rb +1 -0
  17. data/lib/solargraph/parser/region.rb +1 -1
  18. data/lib/solargraph/parser/rubyvm/class_methods.rb +1 -3
  19. data/lib/solargraph/parser/rubyvm/node_chainer.rb +5 -2
  20. data/lib/solargraph/parser.rb +2 -0
  21. data/lib/solargraph/pin/base.rb +1 -1
  22. data/lib/solargraph/pin/block.rb +2 -2
  23. data/lib/solargraph/pin/delegated_method.rb +1 -1
  24. data/lib/solargraph/pin/method.rb +62 -5
  25. data/lib/solargraph/pin/namespace.rb +10 -3
  26. data/lib/solargraph/pin/parameter.rb +9 -10
  27. data/lib/solargraph/pin/signature.rb +9 -1
  28. data/lib/solargraph/rbs_map/conversions.rb +86 -31
  29. data/lib/solargraph/rbs_map/core_fills.rb +9 -10
  30. data/lib/solargraph/rbs_map/core_map.rb +1 -1
  31. data/lib/solargraph/rbs_map.rb +2 -3
  32. data/lib/solargraph/source/chain/array.rb +29 -0
  33. data/lib/solargraph/source/chain/call.rb +14 -30
  34. data/lib/solargraph/source/chain/link.rb +1 -1
  35. data/lib/solargraph/source/chain/z_super.rb +1 -1
  36. data/lib/solargraph/source/chain.rb +9 -10
  37. data/lib/solargraph/source/source_chainer.rb +2 -0
  38. data/lib/solargraph/source.rb +3 -3
  39. data/lib/solargraph/source_map/clip.rb +0 -16
  40. data/lib/solargraph/source_map/mapper.rb +2 -1
  41. data/lib/solargraph/source_map.rb +2 -2
  42. data/lib/solargraph/type_checker.rb +18 -7
  43. data/lib/solargraph/version.rb +1 -1
  44. data/lib/solargraph/workspace.rb +2 -1
  45. data/lib/solargraph/yard_map/mapper.rb +1 -1
  46. data/lib/solargraph/yard_map.rb +6 -5
  47. data/lib/solargraph/yard_tags.rb +20 -0
  48. data/lib/solargraph.rb +2 -3
  49. data/solargraph.gemspec +1 -0
  50. metadata +18 -3
  51. data/lib/yard-solargraph.rb +0 -33
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'solargraph/yard_tags'
4
+
3
5
  module Solargraph
4
6
  module Pin
5
7
  class Namespace < Closure
@@ -9,12 +11,12 @@ module Solargraph
9
11
  # @return [::Symbol] :class or :module
10
12
  attr_reader :type
11
13
 
12
- attr_reader :parameters
14
+ attr_reader :generics
13
15
 
14
16
  # @param type [::Symbol] :class or :module
15
17
  # @param visibility [::Symbol] :public or :private
16
18
  # @param gates [Array<String>]
17
- def initialize type: :class, visibility: :public, gates: [''], parameters: [], **splat
19
+ def initialize type: :class, visibility: :public, gates: [''], generics: nil, **splat
18
20
  # super(location, namespace, name, comments)
19
21
  super(**splat)
20
22
  @type = type
@@ -38,7 +40,7 @@ module Solargraph
38
40
  @closure = Pin::Namespace.new(name: closure_name, gates: [parts.join('::')])
39
41
  @context = nil
40
42
  end
41
- @parameters = parameters
43
+ @generics = generics
42
44
  end
43
45
 
44
46
  def namespace
@@ -89,6 +91,11 @@ module Solargraph
89
91
  [path] + @open_gates
90
92
  end
91
93
  end
94
+
95
+ # @return [Array<String>]
96
+ def generics
97
+ @generics ||= docstring.tags(:generic).map(&:name)
98
+ end
92
99
  end
93
100
  end
94
101
  end
@@ -123,17 +123,16 @@ module Solargraph
123
123
  clip = api_map.clip_at(location.filename, location.range.start)
124
124
  locals = clip.locals - [self]
125
125
  meths = chain.define(api_map, closure, locals)
126
+ receiver_type = chain.base.infer(api_map, closure, locals)
126
127
  meths.each do |meth|
127
- if meth.docstring.has_tag?(:yieldparam_single_parameter)
128
- type = chain.base.infer(api_map, closure, locals)
129
- if type.defined? && !type.subtypes.empty?
130
- bmeth = chain.base.define(api_map, closure, locals).first
131
- return type.subtypes.first.qualify(api_map, bmeth.context.namespace)
132
- end
133
- else
134
- yps = meth.docstring.tags(:yieldparam)
135
- unless yps[index].nil? or yps[index].types.nil? or yps[index].types.empty?
136
- return ComplexType.try_parse(yps[index].types.first).self_to(chain.base.infer(api_map, closure, locals).namespace).qualify(api_map, meth.context.namespace)
128
+ yps = meth.docstring.tags(:yieldparam)
129
+ unless yps[index].nil? or yps[index].types.nil? or yps[index].types.empty?
130
+ yield_type = ComplexType.try_parse(yps[index].types.first)
131
+ if yield_type.generic? && receiver_type.defined?
132
+ namespace_pin = api_map.get_namespace_pins(meth.namespace, closure.namespace).first
133
+ return yield_type.resolve_generics(namespace_pin, receiver_type)
134
+ else
135
+ return yield_type.self_to(chain.base.infer(api_map, closure, locals).namespace).qualify(api_map, meth.context.namespace)
137
136
  end
138
137
  end
139
138
  end
@@ -1,20 +1,28 @@
1
1
  module Solargraph
2
2
  module Pin
3
- class Signature
3
+ class Signature < Base
4
4
  # @return [Array<Parameter>]
5
5
  attr_reader :parameters
6
6
 
7
7
  # @return [ComplexType]
8
8
  attr_reader :return_type
9
9
 
10
+ # @return [self]
10
11
  attr_reader :block
11
12
 
13
+ # @param parameters [Array<Parameter>]
14
+ # @param return_type [ComplexType]
15
+ # @param block [Signature, nil]
12
16
  def initialize parameters, return_type, block = nil
13
17
  @parameters = parameters
14
18
  @return_type = return_type
15
19
  @block = block
16
20
  end
17
21
 
22
+ def identity
23
+ @identity ||= "signature#{object_id}"
24
+ end
25
+
18
26
  def block?
19
27
  !!@block
20
28
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'rbs'
4
+
3
5
  module Solargraph
4
6
  class RbsMap
5
7
  # Functions for converting RBS declarations to Solargraph pins
@@ -25,15 +27,42 @@ module Solargraph
25
27
 
26
28
  private
27
29
 
30
+ # @return Hash{String => RBS::AST::Declarations::TypeAlias}
28
31
  def type_aliases
29
32
  @type_aliases ||= {}
30
33
  end
31
34
 
35
+ # @param loader [RBS::EnvironmentLoader]
36
+ # @return [void]
37
+ def load_environment_to_pins(loader)
38
+ environment = RBS::Environment.from_loader(loader).resolve_type_names
39
+ cursor = pins.length
40
+ environment.declarations.each { |decl| convert_decl_to_pin(decl, Solargraph::Pin::ROOT_PIN) }
41
+ added_pins = pins[cursor..-1]
42
+ add_back_implicit_pins(added_pins)
43
+ end
44
+
45
+ # @param added_pins [Range<Pin>]
46
+ # @return [void]
47
+ def add_back_implicit_pins(added_pins)
48
+ added_pins.each do |pin|
49
+ pin.source = :rbs
50
+ next unless pin.is_a?(Pin::Namespace) && pin.type == :class
51
+ next if pins.any? { |p| p.path == "#{pin.path}.new"}
52
+ pins.push Solargraph::Pin::Method.new(
53
+ location: nil,
54
+ closure: pin,
55
+ name: 'new',
56
+ comments: pin.comments,
57
+ scope: :class
58
+ )
59
+ end
60
+ end
61
+
32
62
  # @param decl [RBS::AST::Declarations::Base]
33
63
  # @param closure [Pin::Closure]
34
64
  # @return [void]
35
65
  def convert_decl_to_pin decl, closure
36
- cursor = pins.length
37
66
  case decl
38
67
  when RBS::AST::Declarations::Class
39
68
  class_decl_to_pin decl
@@ -46,18 +75,10 @@ module Solargraph
46
75
  module_decl_to_pin decl
47
76
  when RBS::AST::Declarations::Constant
48
77
  constant_decl_to_pin decl
49
- end
50
- pins[cursor..-1].each do |pin|
51
- pin.source = :rbs
52
- next unless pin.is_a?(Pin::Namespace) && pin.type == :class
53
- next if pins.any? { |p| p.path == "#{pin.path}.new"}
54
- pins.push Solargraph::Pin::Method.new(
55
- location: nil,
56
- closure: pin.closure,
57
- name: 'new',
58
- comments: pin.comments,
59
- scope: :class
60
- )
78
+ when RBS::AST::Declarations::ClassAlias
79
+ class_alias_decl_to_pin decl
80
+ else
81
+ Solargraph.logger.info "Skipping declaration #{decl.class}"
61
82
  end
62
83
  end
63
84
 
@@ -106,7 +127,7 @@ module Solargraph
106
127
  name: decl.name.relative!.to_s,
107
128
  closure: Solargraph::Pin::ROOT_PIN,
108
129
  comments: decl.comment&.string,
109
- parameters: decl.type_params.map(&:name).map(&:to_s)
130
+ generics: decl.type_params.map(&:name).map(&:to_s)
110
131
  )
111
132
  pins.push class_pin
112
133
  if decl.super_class
@@ -142,16 +163,20 @@ module Solargraph
142
163
  type: :module,
143
164
  name: decl.name.relative!.to_s,
144
165
  closure: Solargraph::Pin::ROOT_PIN,
145
- comments: decl.comment&.string
166
+ comments: decl.comment&.string,
167
+ generics: decl.type_params.map(&:name).map(&:to_s),
146
168
  )
147
169
  pins.push module_pin
148
170
  convert_members_to_pin decl, module_pin
149
171
  end
150
172
 
151
- # @param decl [RBS::AST::Declarations::Constant]
152
- # @return [void]
153
- def constant_decl_to_pin decl
154
- parts = decl.name.relative!.to_s.split('::')
173
+ # @param name [String]
174
+ # @param tag [String]
175
+ # @param comments [String]
176
+ #
177
+ # @return [Solargraph::Pin::Constant]
178
+ def create_constant(name, tag, comments)
179
+ parts = name.split('::')
155
180
  if parts.length > 1
156
181
  name = parts.last
157
182
  closure = pins.select { |pin| pin && pin.path == parts[0..-2].join('::') }.first
@@ -159,15 +184,31 @@ module Solargraph
159
184
  name = parts.first
160
185
  closure = Solargraph::Pin::ROOT_PIN
161
186
  end
162
- pin = Solargraph::Pin::Constant.new(
187
+ constant_pin = Solargraph::Pin::Constant.new(
163
188
  name: name,
164
189
  closure: closure,
165
- comments: decl.comment&.string
190
+ comments: comments
166
191
  )
167
- tag = other_type_to_tag(decl.type)
168
192
  # @todo Class or Module?
169
- pin.docstring.add_tag(YARD::Tags::Tag.new(:return, '', "Class<#{tag}>"))
170
- pins.push pin
193
+ constant_pin.docstring.add_tag(YARD::Tags::Tag.new(:return, '', "Class<#{tag}>"))
194
+ constant_pin
195
+ end
196
+
197
+ # @param decl [RBS::AST::Declarations::ClassAlias]
198
+ # @return [void]
199
+ def class_alias_decl_to_pin decl
200
+ # See https://www.rubydoc.info/gems/rbs/3.4.3/RBS/AST/Declarations/ClassAlias
201
+ new_name = decl.new_name.relative!.to_s
202
+ old_name = decl.old_name.relative!.to_s
203
+
204
+ pins.push create_constant(new_name, old_name, decl.comment&.string)
205
+ end
206
+
207
+ # @param decl [RBS::AST::Declarations::Constant]
208
+ # @return [void]
209
+ def constant_decl_to_pin decl
210
+ tag = other_type_to_tag(decl.type)
211
+ pins.push create_constant(decl.name.relative!.to_s, tag, decl.comment&.string)
171
212
  end
172
213
 
173
214
  # @param decl [RBS::AST::Members::MethodDefinition]
@@ -243,7 +284,8 @@ module Solargraph
243
284
  end
244
285
  type.type.optional_positionals.each do |param|
245
286
  name = param.name ? param.name.to_s : "arg#{arg_num += 1}"
246
- parameters.push Solargraph::Pin::Parameter.new(decl: :optarg, name: name, closure: pin)
287
+ parameters.push Solargraph::Pin::Parameter.new(decl: :optarg, name: name, closure: pin,
288
+ return_type: ComplexType.try_parse(other_type_to_tag(param.type)))
247
289
  end
248
290
  if type.type.rest_positionals
249
291
  name = type.type.rest_positionals.name ? type.type.rest_positionals.name.to_s : "arg#{arg_num += 1}"
@@ -253,13 +295,15 @@ module Solargraph
253
295
  name = param.name ? param.name.to_s : "arg#{arg_num += 1}"
254
296
  parameters.push Solargraph::Pin::Parameter.new(decl: :arg, name: name, closure: pin)
255
297
  end
256
- type.type.required_keywords.each do |orig, _param|
298
+ type.type.required_keywords.each do |orig, param|
257
299
  name = orig ? orig.to_s : "arg#{arg_num += 1}"
258
- parameters.push Solargraph::Pin::Parameter.new(decl: :kwarg, name: name, closure: pin)
300
+ parameters.push Solargraph::Pin::Parameter.new(decl: :kwarg, name: name, closure: pin,
301
+ return_type: ComplexType.try_parse(other_type_to_tag(param.type)))
259
302
  end
260
- type.type.optional_keywords.each do |orig, _param|
303
+ type.type.optional_keywords.each do |orig, param|
261
304
  name = orig ? orig.to_s : "arg#{arg_num += 1}"
262
- parameters.push Solargraph::Pin::Parameter.new(decl: :kwoptarg, name: name, closure: pin)
305
+ parameters.push Solargraph::Pin::Parameter.new(decl: :kwoptarg, name: name, closure: pin,
306
+ return_type: ComplexType.try_parse(other_type_to_tag(param.type)))
263
307
  end
264
308
  if type.type.rest_keywords
265
309
  name = type.type.rest_keywords.name ? type.type.rest_keywords.name.to_s : "arg#{arg_num += 1}"
@@ -329,6 +373,7 @@ module Solargraph
329
373
  )
330
374
  end
331
375
 
376
+ # @param decl [RBS::AST::Members::Alias]
332
377
  def alias_to_pin decl, closure
333
378
  pins.push Solargraph::Pin::MethodAlias.new(
334
379
  name: decl.new_name.to_s,
@@ -345,6 +390,8 @@ module Solargraph
345
390
  'NilClass' => 'nil'
346
391
  }
347
392
 
393
+ # @param type [RBS::AST::Members::MethodDefinition::Overload]
394
+ # @return [String]
348
395
  def method_type_to_tag type
349
396
  if type_aliases.key?(type.type.return_type.to_s)
350
397
  other_type_to_tag(type_aliases[type.type.return_type.to_s].type)
@@ -378,16 +425,24 @@ module Solargraph
378
425
  elsif type.is_a?(RBS::Types::Bases::Void)
379
426
  'void'
380
427
  elsif type.is_a?(RBS::Types::Variable)
381
- "param<#{type.name}>"
428
+ "#{Solargraph::ComplexType::GENERIC_TAG_NAME}<#{type.name}>"
382
429
  elsif type.is_a?(RBS::Types::ClassInstance) #&& !type.args.empty?
383
430
  base = RBS_TO_YARD_TYPE[type.name.relative!.to_s] || type.name.relative!.to_s
384
431
  params = type.args.map { |a| other_type_to_tag(a) }.reject { |t| t == 'undefined' }
385
432
  return base if params.empty?
386
433
  "#{base}<#{params.join(', ')}>"
434
+ elsif type.is_a?(RBS::Types::Bases::Instance)
435
+ 'self'
436
+ elsif type.is_a?(RBS::Types::Bases::Top) || type.is_a?(RBS::Types::Bases::Bottom)
437
+ 'self'
438
+ elsif type.is_a?(RBS::Types::Intersection)
439
+ type.types.map { |member| other_type_to_tag(member) }.join(', ')
440
+ elsif type.is_a?(RBS::Types::Proc)
441
+ 'Proc'
387
442
  elsif type.respond_to?(:name) && type.name.respond_to?(:relative!)
388
443
  RBS_TO_YARD_TYPE[type.name.relative!.to_s] || type.name.relative!.to_s
389
444
  else
390
- Solargraph.logger.warn "Unrecognized RBS type: #{type.class} #{type}"
445
+ Solargraph.logger.warn "Unrecognized RBS type: #{type.class} at #{type.location}"
391
446
  'undefined'
392
447
  end
393
448
  end
@@ -16,8 +16,10 @@ module Solargraph
16
16
  ].map { |k| Pin::Keyword.new(k) }
17
17
 
18
18
  MISSING = [
19
- Solargraph::Pin::Method.new(name: 'tap', scope: :instance, closure: Solargraph::Pin::Namespace.new(name: 'Object')),
20
- Solargraph::Pin::Method.new(name: 'class', scope: :instance, closure: Solargraph::Pin::Namespace.new(name: 'Object'), comments: '@return [Class<self>]')
19
+ Solargraph::Pin::Method.new(name: 'tap', scope: :instance,
20
+ closure: Solargraph::Pin::Namespace.new(name: 'Object')),
21
+ Solargraph::Pin::Method.new(name: 'class', scope: :instance,
22
+ closure: Solargraph::Pin::Namespace.new(name: 'Object'), comments: '@return [Class<self>]')
21
23
  ]
22
24
 
23
25
  YIELDPARAMS = [
@@ -27,7 +29,7 @@ module Solargraph
27
29
  )),
28
30
  Override.from_comment('String#each_line', %(
29
31
  @yieldparam [String]
30
- )),
32
+ ))
31
33
  ]
32
34
 
33
35
  methods_with_yieldparam_subtypes = %w[
@@ -39,16 +41,14 @@ module Solargraph
39
41
  ]
40
42
 
41
43
  YIELDPARAM_SINGLE_PARAMETERS = methods_with_yieldparam_subtypes.map do |path|
42
- Override.from_comment(path, %(
43
- @yieldparam_single_parameter
44
- ))
44
+ Override.from_comment(path, <<~DOC
45
+ @yieldparam [generic<Elem>]
46
+ DOC
47
+ )
45
48
  end
46
49
 
47
50
  CLASS_RETURN_TYPES = [
48
- Override.method_return('Class#new', 'self'),
49
- Override.method_return('Class.new', 'Class<BasicObject>'),
50
51
  Override.method_return('Class#allocate', 'self'),
51
- Override.method_return('Class.allocate', 'Class<BasicObject>'),
52
52
  ]
53
53
 
54
54
  # HACK: Add Errno exception classes
@@ -64,4 +64,3 @@ module Solargraph
64
64
  end
65
65
  end
66
66
  end
67
-
@@ -14,7 +14,7 @@ module Solargraph
14
14
  else
15
15
  loader = RBS::EnvironmentLoader.new(repository: RBS::Repository.new(no_stdlib: false))
16
16
  environment = RBS::Environment.from_loader(loader).resolve_type_names
17
- environment.declarations.each { |decl| convert_decl_to_pin(decl, Solargraph::Pin::ROOT_PIN) }
17
+ load_environment_to_pins(loader)
18
18
  pins.concat RbsMap::CoreFills::ALL
19
19
  processed = ApiMap::Store.new(pins).pins.reject { |p| p.is_a?(Solargraph::Pin::Reference::Override) }
20
20
  pins.replace processed
@@ -24,8 +24,7 @@ module Solargraph
24
24
  loader = RBS::EnvironmentLoader.new(core_root: nil, repository: repository)
25
25
  add_library loader, library
26
26
  return unless resolved?
27
- environment = RBS::Environment.from_loader(loader).resolve_type_names
28
- environment.declarations.each { |decl| convert_decl_to_pin(decl, Solargraph::Pin::ROOT_PIN) }
27
+ load_environment_to_pins(loader)
29
28
  end
30
29
 
31
30
  def path_pin path
@@ -57,7 +56,7 @@ module Solargraph
57
56
  # @return [Boolean] true if adding the library succeeded
58
57
  def add_library loader, library
59
58
  @resolved = if loader.has_library?(library: library, version: nil)
60
- loader.add library: library
59
+ loader.add library: library, version: nil
61
60
  Solargraph.logger.info "#{short_name} successfully loaded library #{library}"
62
61
  true
63
62
  else
@@ -0,0 +1,29 @@
1
+ module Solargraph
2
+ class Source
3
+ class Chain
4
+ class Array < Literal
5
+ # @param type [String]
6
+ def initialize children
7
+ super('::Array')
8
+ @children = children
9
+ end
10
+
11
+ def word
12
+ @word ||= "<#{@type}>"
13
+ end
14
+
15
+ def resolve api_map, name_pin, locals
16
+ child_types = @children.map do |child|
17
+ child.infer(api_map, name_pin, locals).tag
18
+ end
19
+ type = if child_types.uniq.length == 1 && child_types.first != 'undefined'
20
+ "::Array<#{child_types.first}>"
21
+ else
22
+ '::Array'
23
+ end
24
+ [Pin::ProxyType.anonymous(ComplexType.try_parse(type))]
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -11,7 +11,7 @@ module Solargraph
11
11
  attr_reader :arguments
12
12
 
13
13
  # @param word [String]
14
- # @param arguments [Array<Chain>]
14
+ # @param arguments [::Array<Chain>]
15
15
  # @param with_block [Boolean] True if the chain is inside a block
16
16
  # @param head [Boolean] True if the call is the start of its chain
17
17
  def initialize word, arguments = [], with_block = false
@@ -26,9 +26,10 @@ module Solargraph
26
26
 
27
27
  # @param api_map [ApiMap]
28
28
  # @param name_pin [Pin::Base]
29
- # @param locals [Array<Pin::Base>]
29
+ # @param locals [::Array<Pin::Base>]
30
30
  def resolve api_map, name_pin, locals
31
31
  return super_pins(api_map, name_pin) if word == 'super'
32
+ return yield_pins(api_map, name_pin) if word == 'yield'
32
33
  found = if head?
33
34
  locals.select { |p| p.name == word }
34
35
  else
@@ -75,27 +76,12 @@ module Solargraph
75
76
  end
76
77
  end
77
78
  if match
78
- type = extra_return_type(p.docstring, context)
79
- break if type
80
79
  type = with_params(ol.return_type.self_to(context.to_s), context).qualify(api_map, context.namespace) if ol.return_type.defined?
81
80
  type ||= ComplexType::UNDEFINED
82
81
  end
83
82
  break if type.defined?
84
83
  end
85
84
  next p.proxy(type) if type.defined?
86
- type = extra_return_type(p.docstring, context)
87
- if type
88
- next Solargraph::Pin::Method.new(
89
- location: p.location,
90
- closure: p.closure,
91
- name: p.name,
92
- comments: "@return [#{context.subtypes.first.to_s}]",
93
- scope: p.scope,
94
- visibility: p.visibility,
95
- parameters: p.parameters,
96
- node: p.node
97
- )
98
- end
99
85
  if p.is_a?(Pin::Method) && !p.macros.empty?
100
86
  result = process_macro(p, api_map, context, locals)
101
87
  next result unless result.return_type.undefined?
@@ -170,18 +156,6 @@ module Solargraph
170
156
  Pin::ProxyType.anonymous(ComplexType::UNDEFINED)
171
157
  end
172
158
 
173
- # @param docstring [YARD::Docstring]
174
- # @param context [ComplexType]
175
- # @return [ComplexType]
176
- def extra_return_type docstring, context
177
- if docstring.has_tag?(:return_single_parameter) #&& context.subtypes.one?
178
- return context.subtypes.first || ComplexType::UNDEFINED
179
- elsif docstring.has_tag?(:return_value_parameter) && context.value_types.one?
180
- return context.value_types.first
181
- end
182
- nil
183
- end
184
-
185
159
  # @param arguments [Array<Chain>]
186
160
  # @param signature [Pin::Signature]
187
161
  # @return [Boolean]
@@ -197,12 +171,22 @@ module Solargraph
197
171
 
198
172
  # @param api_map [ApiMap]
199
173
  # @param name_pin [Pin::Base]
200
- # @return [Array<Pin::Base>]
174
+ # @return [::Array<Pin::Base>]
201
175
  def super_pins api_map, name_pin
202
176
  pins = api_map.get_method_stack(name_pin.namespace, name_pin.name, scope: name_pin.context.scope)
203
177
  pins.reject{|p| p.path == name_pin.path}
204
178
  end
205
179
 
180
+ # @param api_map [ApiMap]
181
+ # @param name_pin [Pin::Base]
182
+ # @return [::Array<Pin::Base>]
183
+ def yield_pins api_map, name_pin
184
+ method_pin = api_map.get_method_stack(name_pin.namespace, name_pin.name, scope: name_pin.context.scope).first
185
+ return [] if method_pin.nil?
186
+
187
+ method_pin.signatures.map(&:block).compact
188
+ end
189
+
206
190
  # @param type [ComplexType]
207
191
  # @param context [ComplexType]
208
192
  def with_params type, context
@@ -24,7 +24,7 @@ module Solargraph
24
24
  # @param api_map [ApiMap]
25
25
  # @param name_pin [Pin::Base]
26
26
  # @param locals [Array<Pin::Base>]
27
- # @return [Array<Pin::Base>]
27
+ # @return [::Array<Pin::Base>]
28
28
  def resolve api_map, name_pin, locals
29
29
  []
30
30
  end
@@ -20,7 +20,7 @@ module Solargraph
20
20
 
21
21
  # @param api_map [ApiMap]
22
22
  # @param name_pin [Pin::Base]
23
- # @param locals [Array<Pin::Base>]
23
+ # @param locals [::Array<Pin::Base>]
24
24
  def resolve api_map, name_pin, locals
25
25
  return super_pins(api_map, name_pin)
26
26
  end
@@ -23,6 +23,7 @@ module Solargraph
23
23
  autoload :BlockVariable, 'solargraph/source/chain/block_variable'
24
24
  autoload :ZSuper, 'solargraph/source/chain/z_super'
25
25
  autoload :Hash, 'solargraph/source/chain/hash'
26
+ autoload :Array, 'solargraph/source/chain/array'
26
27
 
27
28
  @@inference_stack = []
28
29
  @@inference_depth = 0
@@ -30,12 +31,12 @@ module Solargraph
30
31
  UNDEFINED_CALL = Chain::Call.new('<undefined>')
31
32
  UNDEFINED_CONSTANT = Chain::Constant.new('<undefined>')
32
33
 
33
- # @return [Array<Source::Chain::Link>]
34
+ # @return [::Array<Source::Chain::Link>]
34
35
  attr_reader :links
35
36
 
36
37
  attr_reader :node
37
38
 
38
- # @param links [Array<Chain::Link>]
39
+ # @param links [::Array<Chain::Link>]
39
40
  def initialize links, node = nil, splat = false
40
41
  @links = links.clone
41
42
  @links.push UNDEFINED_CALL if @links.empty?
@@ -57,7 +58,7 @@ module Solargraph
57
58
  # @param api_map [ApiMap]
58
59
  # @param name_pin [Pin::Base]
59
60
  # @param locals [Array<Pin::Base>]
60
- # @return [Array<Pin::Base>]
61
+ # @return [::Array<Pin::Base>]
61
62
  def define api_map, name_pin, locals
62
63
  return [] if undefined?
63
64
  working_pin = name_pin
@@ -122,17 +123,13 @@ module Solargraph
122
123
  pins.each do |pin|
123
124
  # Avoid infinite recursion
124
125
  next if @@inference_stack.include?(pin.identity)
126
+
125
127
  @@inference_stack.push pin.identity
126
128
  type = pin.typify(api_map)
127
129
  @@inference_stack.pop
128
130
  if type.defined?
129
- if type.parameterized?
130
- type = type.resolve_parameters(pin.closure, context)
131
- # idx = pin.closure.parameters.index(type.subtypes.first.name)
132
- # next if idx.nil?
133
- # param_type = context.return_type.all_params[idx]
134
- # next unless param_type
135
- # type = ComplexType.try_parse(param_type.to_s)
131
+ if type.generic?
132
+ type = type.resolve_generics(pin.closure, context.return_type)
136
133
  end
137
134
  if type.defined?
138
135
  possibles.push type
@@ -143,10 +140,12 @@ module Solargraph
143
140
  if possibles.empty?
144
141
  # Limit method inference recursion
145
142
  return ComplexType::UNDEFINED if @@inference_depth >= 10 && pins.first.is_a?(Pin::Method)
143
+
146
144
  @@inference_depth += 1
147
145
  pins.each do |pin|
148
146
  # Avoid infinite recursion
149
147
  next if @@inference_stack.include?(pin.identity)
148
+
150
149
  @@inference_stack.push pin.identity
151
150
  type = pin.probe(api_map)
152
151
  @@inference_stack.pop
@@ -47,6 +47,8 @@ module Solargraph
47
47
  elsif source.parsed? && source.repaired? && end_of_phrase == '.'
48
48
  node, parent = source.tree_at(fixed_position.line, fixed_position.column)[0..2]
49
49
  node = Parser.parse(fixed_phrase) if node.nil?
50
+ elsif source.repaired?
51
+ node = Parser.parse(fixed_phrase)
50
52
  else
51
53
  node, parent = source.tree_at(fixed_position.line, fixed_position.column)[0..2] unless source.error_ranges.any?{|r| r.nil? || r.include?(fixed_position)}
52
54
  # Exception for positions that chain literal nodes in unsynchronized sources
@@ -33,7 +33,7 @@ module Solargraph
33
33
  attr_reader :version
34
34
 
35
35
  # @param code [String]
36
- # @param filename [String]
36
+ # @param filename [String, nil]
37
37
  # @param version [Integer]
38
38
  def initialize code, filename = nil, version = 0
39
39
  @code = normalize(code)
@@ -332,7 +332,7 @@ module Solargraph
332
332
 
333
333
  # @param top [Parser::AST::Node]
334
334
  # @param result [Array<Range>]
335
- # @param parent [Symbol]
335
+ # @param parent [Symbol, nil]
336
336
  # @return [void]
337
337
  def inner_folding_ranges top, result = [], parent = nil
338
338
  return unless Parser.is_ast_node?(top)
@@ -503,7 +503,7 @@ module Solargraph
503
503
  end
504
504
 
505
505
  # @param code [String]
506
- # @param filename [String]
506
+ # @param filename [String, nil]
507
507
  # @param version [Integer]
508
508
  # @return [Solargraph::Source]
509
509
  def load_string code, filename = nil, version = 0
@@ -115,21 +115,6 @@ module Solargraph
115
115
  @context_pin ||= source_map.locate_named_path_pin(cursor.node_position.line, cursor.node_position.character)
116
116
  end
117
117
 
118
- # @return [Array<Pin::Base>]
119
- def yielded_self_pins
120
- return [] unless block.is_a?(Pin::Block) && block.receiver
121
- chain = Parser.chain(block.receiver, source_map.source.filename)
122
- receiver_pin = chain.define(api_map, context_pin, locals).first
123
- return [] if receiver_pin.nil?
124
- result = []
125
- ys = receiver_pin.docstring.tag(:yieldpublic)
126
- unless ys.nil? || ys.types.empty?
127
- ysct = ComplexType.try_parse(*ys.types).qualify(api_map, receiver_pin.context.namespace)
128
- result.concat api_map.get_complex_type_methods(ysct, '', false)
129
- end
130
- result
131
- end
132
-
133
118
  # @return [Array<Pin::KeywordParam]
134
119
  def complete_keyword_parameters
135
120
  return [] unless cursor.argument? && cursor.chain.links.one? && cursor.word =~ /^[a-z0-9_]*:?$/
@@ -226,7 +211,6 @@ module Solargraph
226
211
  result.concat api_map.get_methods('Kernel')
227
212
  # result.concat ApiMap.keywords
228
213
  result.concat api_map.keyword_pins.to_a
229
- result.concat yielded_self_pins
230
214
  end
231
215
  end
232
216
  package_completions(result)