solargraph 0.47.2 → 0.50.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 (70) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +1 -0
  3. data/.github/workflows/rspec.yml +1 -1
  4. data/CHANGELOG.md +40 -0
  5. data/LICENSE +1 -1
  6. data/README.md +9 -3
  7. data/SPONSORS.md +4 -4
  8. data/lib/solargraph/api_map/store.rb +13 -1
  9. data/lib/solargraph/api_map.rb +30 -12
  10. data/lib/solargraph/cache.rb +53 -0
  11. data/lib/solargraph/complex_type/type_methods.rb +10 -6
  12. data/lib/solargraph/complex_type/unique_type.rb +57 -0
  13. data/lib/solargraph/complex_type.rb +32 -3
  14. data/lib/solargraph/convention/rakefile.rb +17 -0
  15. data/lib/solargraph/convention.rb +2 -0
  16. data/lib/solargraph/diagnostics/rubocop.rb +17 -3
  17. data/lib/solargraph/diagnostics/rubocop_helpers.rb +3 -1
  18. data/lib/solargraph/language_server/host/cataloger.rb +1 -1
  19. data/lib/solargraph/language_server/host.rb +22 -18
  20. data/lib/solargraph/language_server/message/extended/download_core.rb +1 -5
  21. data/lib/solargraph/language_server/message/initialize.rb +2 -0
  22. data/lib/solargraph/language_server/message/text_document/formatting.rb +1 -1
  23. data/lib/solargraph/language_server/message/text_document/signature_help.rb +1 -6
  24. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +10 -3
  25. data/lib/solargraph/library.rb +25 -20
  26. data/lib/solargraph/parser/legacy/node_processors/casgn_node.rb +12 -2
  27. data/lib/solargraph/parser/legacy/node_processors/sclass_node.rb +24 -3
  28. data/lib/solargraph/parser/rubyvm/class_methods.rb +6 -1
  29. data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +13 -2
  30. data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +20 -8
  31. data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +14 -3
  32. data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +14 -3
  33. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +4 -2
  34. data/lib/solargraph/parser/rubyvm/node_wrapper.rb +47 -0
  35. data/lib/solargraph/pin/base.rb +5 -2
  36. data/lib/solargraph/pin/base_variable.rb +1 -1
  37. data/lib/solargraph/pin/conversions.rb +2 -6
  38. data/lib/solargraph/pin/method.rb +100 -10
  39. data/lib/solargraph/pin/namespace.rb +4 -1
  40. data/lib/solargraph/pin/parameter.rb +8 -3
  41. data/lib/solargraph/pin/signature.rb +23 -0
  42. data/lib/solargraph/pin.rb +1 -0
  43. data/lib/solargraph/rbs_map/conversions.rb +394 -0
  44. data/lib/solargraph/rbs_map/core_fills.rb +61 -0
  45. data/lib/solargraph/rbs_map/core_map.rb +38 -0
  46. data/lib/solargraph/rbs_map/core_signs.rb +33 -0
  47. data/lib/solargraph/rbs_map/stdlib_map.rb +36 -0
  48. data/lib/solargraph/rbs_map.rb +73 -0
  49. data/lib/solargraph/shell.rb +50 -32
  50. data/lib/solargraph/source/chain/call.rb +35 -24
  51. data/lib/solargraph/source/chain.rb +22 -7
  52. data/lib/solargraph/source_map/clip.rb +5 -0
  53. data/lib/solargraph/source_map/mapper.rb +8 -4
  54. data/lib/solargraph/type_checker.rb +71 -65
  55. data/lib/solargraph/version.rb +1 -1
  56. data/lib/solargraph/views/environment.erb +2 -2
  57. data/lib/solargraph/workspace.rb +11 -14
  58. data/lib/solargraph/yard_map/mapper/to_method.rb +7 -4
  59. data/lib/solargraph/yard_map.rb +35 -194
  60. data/lib/solargraph.rb +2 -2
  61. data/solargraph.gemspec +11 -6
  62. metadata +46 -37
  63. data/.travis.yml +0 -19
  64. data/lib/solargraph/compat.rb +0 -37
  65. data/lib/solargraph/yard_map/core_docs.rb +0 -170
  66. data/lib/solargraph/yard_map/core_fills.rb +0 -208
  67. data/lib/solargraph/yard_map/core_gen.rb +0 -76
  68. data/lib/solargraph/yard_map/rdoc_to_yard.rb +0 -140
  69. data/lib/solargraph/yard_map/stdlib_fills.rb +0 -43
  70. data/yardoc/2.2.2.tar.gz +0 -0
@@ -18,13 +18,18 @@ module Solargraph
18
18
 
19
19
  # @param visibility [::Symbol] :public, :protected, or :private
20
20
  # @param explicit [Boolean]
21
- def initialize visibility: :public, explicit: true, parameters: [], node: nil, attribute: false, **splat
21
+ # @param parameters [Array<Pin::Parameter>]
22
+ # @param node [Parser::AST::Node, RubyVM::AbstractSyntaxTree::Node]
23
+ # @param attribute [Boolean]
24
+ def initialize visibility: :public, explicit: true, parameters: [], node: nil, attribute: false, signatures: nil, anon_splat: false, **splat
22
25
  super(**splat)
23
26
  @visibility = visibility
24
27
  @explicit = explicit
25
28
  @parameters = parameters
26
29
  @node = node
27
30
  @attribute = attribute
31
+ @signatures = signatures
32
+ @anon_splat = anon_splat
28
33
  end
29
34
 
30
35
  # @return [Array<String>]
@@ -41,7 +46,45 @@ module Solargraph
41
46
  end
42
47
 
43
48
  def return_type
44
- @return_type ||= generate_complex_type
49
+ @return_type ||= ComplexType.try_parse(*signatures.map(&:return_type).map(&:to_s))
50
+ end
51
+
52
+ # @return [Array<Signature>]
53
+ def signatures
54
+ @signatures ||= begin
55
+ top_type = generate_complex_type
56
+ result = []
57
+ result.push Signature.new(parameters, top_type) if top_type.defined?
58
+ result.concat(overloads.map { |meth| Signature.new(meth.parameters, meth.return_type) })
59
+ result.push Signature.new(parameters, top_type) if result.empty?
60
+ result
61
+ end
62
+ end
63
+
64
+ # @return [String]
65
+ def detail
66
+ # This property is not cached in an instance variable because it can
67
+ # change when pins get proxied.
68
+ detail = String.new
69
+ detail += if signatures.length > 1
70
+ "(*) "
71
+ else
72
+ "(#{signatures.first.parameters.map(&:full).join(', ')}) " unless signatures.first.parameters.empty?
73
+ end.to_s
74
+ detail += "=#{probed? ? '~' : (proxied? ? '^' : '>')} #{return_type.to_s}" unless return_type.undefined?
75
+ detail.strip!
76
+ return nil if detail.empty?
77
+ detail
78
+ end
79
+
80
+ # @return [Array<Hash>]
81
+ def signature_help
82
+ @signature_help ||= signatures.map do |sig|
83
+ {
84
+ label: name + '(' + sig.parameters.map(&:full).join(', ') + ')',
85
+ documentation: documentation
86
+ }
87
+ end
45
88
  end
46
89
 
47
90
  def path
@@ -119,27 +162,60 @@ module Solargraph
119
162
  # @return [Array<Pin::Method>]
120
163
  def overloads
121
164
  @overloads ||= docstring.tags(:overload).map do |tag|
122
- Solargraph::Pin::Method.new(
123
- name: name,
124
- closure: self,
125
- # args: tag.parameters.map(&:first),
126
- parameters: tag.parameters.map do |src|
165
+ Pin::Signature.new(
166
+ tag.parameters.map do |src|
167
+ name, decl = parse_overload_param(src.first)
127
168
  Pin::Parameter.new(
128
169
  location: location,
129
170
  closure: self,
130
171
  comments: tag.docstring.all.to_s,
131
- name: src.first,
172
+ name: name,
173
+ decl: decl,
132
174
  presence: location ? location.range : nil,
133
- decl: :arg
175
+ return_type: param_type_from_name(tag, src.first)
134
176
  )
135
177
  end,
136
- comments: tag.docstring.all.to_s
178
+ ComplexType.try_parse(*tag.docstring.tags(:return).flat_map(&:types))
137
179
  )
138
180
  end
181
+ @overloads
182
+ end
183
+
184
+ def anon_splat?
185
+ @anon_splat
139
186
  end
140
187
 
141
188
  private
142
189
 
190
+ def select_decl name, asgn
191
+ if name.start_with?('**')
192
+ :kwrestarg
193
+ elsif name.start_with?('*')
194
+ :restarg
195
+ elsif name.start_with?('&')
196
+ :blockarg
197
+ elsif name.end_with?(':') && asgn
198
+ :kwoptarg
199
+ elsif name.end_with?(':')
200
+ :kwarg
201
+ elsif asgn
202
+ :optarg
203
+ else
204
+ :arg
205
+ end
206
+ end
207
+
208
+ def clean_param name
209
+ name.gsub(/[*&:]/, '')
210
+ end
211
+
212
+ # @param tag [YARD::Tags::OverloadTag]
213
+ def param_type_from_name(tag, name)
214
+ param = tag.tags(:param).select { |t| t.name == name }.first
215
+ return ComplexType::UNDEFINED unless param
216
+ ComplexType.try_parse(*param.types)
217
+ end
218
+
143
219
  # @return [ComplexType]
144
220
  def generate_complex_type
145
221
  tags = docstring.tags(:return).map(&:types).flatten.reject(&:nil?)
@@ -240,6 +316,20 @@ module Solargraph
240
316
  return ComplexType::UNDEFINED if types.empty?
241
317
  ComplexType.try_parse(*types.map(&:tag).uniq)
242
318
  end
319
+
320
+ # When YARD parses an overload tag, it includes rest modifiers in the parameters names.
321
+ #
322
+ # @param arg [String]
323
+ # @return [Array(String, Symbol)]
324
+ def parse_overload_param(name)
325
+ if name.start_with?('**')
326
+ [name[2..-1], :kwrestarg]
327
+ elsif name.start_with?('*')
328
+ [name[1..-1], :restarg]
329
+ else
330
+ [name, :arg]
331
+ end
332
+ end
243
333
  end
244
334
  end
245
335
  end
@@ -9,10 +9,12 @@ module Solargraph
9
9
  # @return [::Symbol] :class or :module
10
10
  attr_reader :type
11
11
 
12
+ attr_reader :parameters
13
+
12
14
  # @param type [::Symbol] :class or :module
13
15
  # @param visibility [::Symbol] :public or :private
14
16
  # @param gates [Array<String>]
15
- def initialize type: :class, visibility: :public, gates: [''], **splat
17
+ def initialize type: :class, visibility: :public, gates: [''], parameters: [], **splat
16
18
  # super(location, namespace, name, comments)
17
19
  super(**splat)
18
20
  @type = type
@@ -36,6 +38,7 @@ module Solargraph
36
38
  @closure = Pin::Namespace.new(name: closure_name, gates: [parts.join('::')])
37
39
  @context = nil
38
40
  end
41
+ @parameters = parameters
39
42
  end
40
43
 
41
44
  def namespace
@@ -9,10 +9,11 @@ module Solargraph
9
9
  # @return [String]
10
10
  attr_reader :asgn_code
11
11
 
12
- def initialize decl: :arg, asgn_code: nil, **splat
12
+ def initialize decl: :arg, asgn_code: nil, return_type: nil, **splat
13
13
  super(**splat)
14
14
  @asgn_code = asgn_code
15
15
  @decl = decl
16
+ @return_type = return_type
16
17
  end
17
18
 
18
19
  def keyword?
@@ -31,14 +32,18 @@ module Solargraph
31
32
  decl == :restarg || decl == :kwrestarg
32
33
  end
33
34
 
35
+ def block?
36
+ [:block, :blockarg].include?(decl)
37
+ end
38
+
34
39
  def full
35
40
  case decl
36
41
  when :optarg
37
- "#{name} = #{asgn_code}"
42
+ "#{name} = #{asgn_code || '?'}"
38
43
  when :kwarg
39
44
  "#{name}:"
40
45
  when :kwoptarg
41
- "#{name}: #{asgn_code}"
46
+ "#{name}: #{asgn_code || '?'}"
42
47
  when :restarg
43
48
  "*#{name}"
44
49
  when :kwrestarg
@@ -0,0 +1,23 @@
1
+ module Solargraph
2
+ module Pin
3
+ class Signature
4
+ # @return [Array<Parameter>]
5
+ attr_reader :parameters
6
+
7
+ # @return [ComplexType]
8
+ attr_reader :return_type
9
+
10
+ attr_reader :block
11
+
12
+ def initialize parameters, return_type, block = nil
13
+ @parameters = parameters
14
+ @return_type = return_type
15
+ @block = block
16
+ end
17
+
18
+ def block?
19
+ !!@block
20
+ end
21
+ end
22
+ end
23
+ end
@@ -10,6 +10,7 @@ module Solargraph
10
10
  autoload :Conversions, 'solargraph/pin/conversions'
11
11
  autoload :Base, 'solargraph/pin/base'
12
12
  autoload :Method, 'solargraph/pin/method'
13
+ autoload :Signature, 'solargraph/pin/signature'
13
14
  autoload :MethodAlias, 'solargraph/pin/method_alias'
14
15
  autoload :BaseVariable, 'solargraph/pin/base_variable'
15
16
  autoload :InstanceVariable, 'solargraph/pin/instance_variable'
@@ -0,0 +1,394 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ class RbsMap
5
+ # Functions for converting RBS declarations to Solargraph pins
6
+ #
7
+ module Conversions
8
+ # A container for tracking the current context of the RBS conversion
9
+ # process, e.g., what visibility is declared for methods in the current
10
+ # scope
11
+ #
12
+ class Context
13
+ attr_reader :visibility
14
+
15
+ # @param visibility [Symbol]
16
+ def initialize visibility = :public
17
+ @visibility = visibility
18
+ end
19
+ end
20
+
21
+ # @return [Array<Pin::Base>]
22
+ def pins
23
+ @pins ||= []
24
+ end
25
+
26
+ private
27
+
28
+ def type_aliases
29
+ @type_aliases ||= {}
30
+ end
31
+
32
+ # @param decl [RBS::AST::Declarations::Base]
33
+ # @param closure [Pin::Closure]
34
+ # @return [void]
35
+ def convert_decl_to_pin decl, closure
36
+ cursor = pins.length
37
+ case decl
38
+ when RBS::AST::Declarations::Class
39
+ class_decl_to_pin decl
40
+ when RBS::AST::Declarations::Interface
41
+ # STDERR.puts "Skipping interface #{decl.name.relative!}"
42
+ interface_decl_to_pin decl
43
+ when RBS::AST::Declarations::Alias
44
+ type_aliases[decl.name.to_s] = decl
45
+ when RBS::AST::Declarations::Module
46
+ module_decl_to_pin decl
47
+ when RBS::AST::Declarations::Constant
48
+ 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
+ )
61
+ end
62
+ end
63
+
64
+ def convert_members_to_pin decl, closure
65
+ context = Context.new
66
+ decl.members.each { |m| context = convert_member_to_pin(m, closure, context) }
67
+ end
68
+
69
+ def convert_member_to_pin member, closure, context
70
+ case member
71
+ when RBS::AST::Members::MethodDefinition
72
+ method_def_to_pin(member, closure)
73
+ when RBS::AST::Members::AttrReader
74
+ attr_reader_to_pin(member, closure)
75
+ when RBS::AST::Members::AttrWriter
76
+ attr_writer_to_pin(member, closure)
77
+ when RBS::AST::Members::AttrAccessor
78
+ attr_accessor_to_pin(member, closure)
79
+ when RBS::AST::Members::Include
80
+ include_to_pin(member, closure)
81
+ when RBS::AST::Members::Prepend
82
+ prepend_to_pin(member, closure)
83
+ when RBS::AST::Members::Extend
84
+ extend_to_pin(member, closure)
85
+ when RBS::AST::Members::Alias
86
+ alias_to_pin(member, closure)
87
+ when RBS::AST::Members::InstanceVariable
88
+ ivar_to_pin(member, closure)
89
+ when RBS::AST::Members::Public
90
+ return Context.new(visibility: :public)
91
+ when RBS::AST::Members::Private
92
+ return Context.new(visibility: :private)
93
+ when RBS::AST::Declarations::Base
94
+ convert_decl_to_pin(member, closure)
95
+ else
96
+ Solargraph.logger.warn "Skipping member #{member.class}"
97
+ end
98
+ context
99
+ end
100
+
101
+ # @param decl [RBS::AST::Declarations::Class]
102
+ # @return [void]
103
+ def class_decl_to_pin decl
104
+ class_pin = Solargraph::Pin::Namespace.new(
105
+ type: :class,
106
+ name: decl.name.relative!.to_s,
107
+ closure: Solargraph::Pin::ROOT_PIN,
108
+ comments: decl.comment&.string,
109
+ parameters: decl.type_params.map(&:name).map(&:to_s)
110
+ )
111
+ pins.push class_pin
112
+ if decl.super_class
113
+ pins.push Solargraph::Pin::Reference::Superclass.new(
114
+ closure: class_pin,
115
+ name: decl.super_class.name.relative!.to_s
116
+ )
117
+ end
118
+ convert_members_to_pin decl, class_pin
119
+ end
120
+
121
+ # @param decl [RBS::AST::Declarations::Interface]
122
+ # @return [void]
123
+ def interface_decl_to_pin decl
124
+ class_pin = Solargraph::Pin::Namespace.new(
125
+ type: :module,
126
+ name: decl.name.relative!.to_s,
127
+ closure: Solargraph::Pin::ROOT_PIN,
128
+ comments: decl.comment&.string,
129
+ # HACK: Using :hidden to keep interfaces from appearing in
130
+ # autocompletion
131
+ visibility: :hidden
132
+ )
133
+ class_pin.docstring.add_tag(YARD::Tags::Tag.new(:abstract, '(RBS interface)'))
134
+ pins.push class_pin
135
+ convert_members_to_pin decl, class_pin
136
+ end
137
+
138
+ # @param decl [RBS::AST::Declarations::Module]
139
+ # @return [void]
140
+ def module_decl_to_pin decl
141
+ module_pin = Solargraph::Pin::Namespace.new(
142
+ type: :module,
143
+ name: decl.name.relative!.to_s,
144
+ closure: Solargraph::Pin::ROOT_PIN,
145
+ comments: decl.comment&.string
146
+ )
147
+ pins.push module_pin
148
+ convert_members_to_pin decl, module_pin
149
+ end
150
+
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('::')
155
+ if parts.length > 1
156
+ name = parts.last
157
+ closure = pins.select { |pin| pin && pin.path == parts[0..-2].join('::') }.first
158
+ else
159
+ name = parts.first
160
+ closure = Solargraph::Pin::ROOT_PIN
161
+ end
162
+ pin = Solargraph::Pin::Constant.new(
163
+ name: name,
164
+ closure: closure,
165
+ comments: decl.comment&.string
166
+ )
167
+ tag = other_type_to_tag(decl.type)
168
+ # @todo Class or Module?
169
+ pin.docstring.add_tag(YARD::Tags::Tag.new(:return, '', "Class<#{tag}>"))
170
+ pins.push pin
171
+ end
172
+
173
+ # @param decl [RBS::AST::Members::MethodDefinition]
174
+ # @param closure [Pin::Closure]
175
+ # @return [void]
176
+ def method_def_to_pin decl, closure
177
+ if decl.instance?
178
+ pin = Solargraph::Pin::Method.new(
179
+ name: decl.name.to_s,
180
+ closure: closure,
181
+ comments: decl.comment&.string,
182
+ scope: :instance,
183
+ signatures: []
184
+ )
185
+ pin.signatures.concat method_def_to_sigs(decl, pin)
186
+ pins.push pin
187
+ if pin.name == 'initialize'
188
+ pins.push Solargraph::Pin::Method.new(
189
+ location: pin.location,
190
+ closure: pin.closure,
191
+ name: 'new',
192
+ comments: pin.comments,
193
+ scope: :class,
194
+ signatures: pin.signatures
195
+ )
196
+ pins.last.signatures.replace(
197
+ pin.signatures.map do |p|
198
+ Pin::Signature.new(
199
+ p.parameters,
200
+ ComplexType::SELF
201
+ )
202
+ end
203
+ )
204
+ # @todo Is this necessary?
205
+ # pin.instance_variable_set(:@visibility, :private)
206
+ # pin.instance_variable_set(:@return_type, ComplexType::VOID)
207
+ end
208
+ end
209
+ if decl.singleton?
210
+ pin = Solargraph::Pin::Method.new(
211
+ name: decl.name.to_s,
212
+ closure: closure,
213
+ comments: decl.comment&.string,
214
+ scope: :class,
215
+ signatures: []
216
+ )
217
+ pin.signatures.concat method_def_to_sigs(decl, pin)
218
+ pins.push pin
219
+ end
220
+ end
221
+
222
+ # @param decl [RBS::AST::Members::MethodDefinition]
223
+ # @param pin [Pin::Method]
224
+ def method_def_to_sigs decl, pin
225
+ decl.types.map do |type|
226
+ parameters, return_type = parts_of_function(type, pin)
227
+ block = if type.block
228
+ Pin::Signature.new(*parts_of_function(type.block, pin))
229
+ end
230
+ return_type = ComplexType.try_parse(method_type_to_tag(type))
231
+ Pin::Signature.new(parameters, return_type, block)
232
+ end
233
+ end
234
+
235
+ def parts_of_function type, pin
236
+ parameters = []
237
+ arg_num = -1
238
+ type.type.required_positionals.each do |param|
239
+ name = param.name ? param.name.to_s : "arg#{arg_num += 1}"
240
+ parameters.push Solargraph::Pin::Parameter.new(decl: :arg, name: name, closure: pin, return_type: ComplexType.try_parse(other_type_to_tag(param.type)))
241
+ end
242
+ type.type.optional_positionals.each do |param|
243
+ name = param.name ? param.name.to_s : "arg#{arg_num += 1}"
244
+ parameters.push Solargraph::Pin::Parameter.new(decl: :optarg, name: name, closure: pin)
245
+ end
246
+ if type.type.rest_positionals
247
+ name = type.type.rest_positionals.name ? type.type.rest_positionals.name.to_s : "arg#{arg_num += 1}"
248
+ parameters.push Solargraph::Pin::Parameter.new(decl: :restarg, name: name, closure: pin)
249
+ end
250
+ type.type.trailing_positionals.each do |param|
251
+ name = param.name ? param.name.to_s : "arg#{arg_num += 1}"
252
+ parameters.push Solargraph::Pin::Parameter.new(decl: :arg, name: name, closure: pin)
253
+ end
254
+ type.type.required_keywords.each do |orig, _param|
255
+ name = orig ? orig.to_s : "arg#{arg_num += 1}"
256
+ parameters.push Solargraph::Pin::Parameter.new(decl: :kwarg, name: name, closure: pin)
257
+ end
258
+ type.type.optional_keywords.each do |orig, _param|
259
+ name = orig ? orig.to_s : "arg#{arg_num += 1}"
260
+ parameters.push Solargraph::Pin::Parameter.new(decl: :kwoptarg, name: name, closure: pin)
261
+ end
262
+ if type.type.rest_keywords
263
+ name = type.type.rest_keywords.name ? type.type.rest_keywords.name.to_s : "arg#{arg_num += 1}"
264
+ parameters.push Solargraph::Pin::Parameter.new(decl: :kwrestarg, name: type.type.rest_keywords.name.to_s, closure: pin)
265
+ end
266
+ return_type = ComplexType.try_parse(method_type_to_tag(type))
267
+ [parameters, return_type]
268
+ end
269
+
270
+ def attr_reader_to_pin(decl, closure)
271
+ pin = Solargraph::Pin::Method.new(
272
+ name: decl.name.to_s,
273
+ closure: closure,
274
+ comments: decl.comment&.string,
275
+ scope: :instance,
276
+ attribute: true
277
+ )
278
+ pin.docstring.add_tag(YARD::Tags::Tag.new(:return, '', other_type_to_tag(decl.type)))
279
+ pins.push pin
280
+ end
281
+
282
+ def attr_writer_to_pin(decl, closure)
283
+ pin = Solargraph::Pin::Method.new(
284
+ name: "#{decl.name.to_s}=",
285
+ closure: closure,
286
+ comments: decl.comment&.string,
287
+ scope: :instance,
288
+ attribute: true
289
+ )
290
+ pin.docstring.add_tag(YARD::Tags::Tag.new(:return, '', other_type_to_tag(decl.type)))
291
+ pins.push pin
292
+ end
293
+
294
+ def attr_accessor_to_pin(decl, closure)
295
+ attr_reader_to_pin(decl, closure)
296
+ attr_writer_to_pin(decl, closure)
297
+ end
298
+
299
+ def ivar_to_pin(decl, closure)
300
+ pin = Solargraph::Pin::InstanceVariable.new(
301
+ name: decl.name.to_s,
302
+ closure: closure,
303
+ comments: decl.comment&.string
304
+ )
305
+ pin.docstring.add_tag(YARD::Tags::Tag.new(:type, '', other_type_to_tag(decl.type)))
306
+ pins.push pin
307
+ end
308
+
309
+ def include_to_pin decl, closure
310
+ pins.push Solargraph::Pin::Reference::Include.new(
311
+ name: decl.name.relative!.to_s,
312
+ closure: closure
313
+ )
314
+ end
315
+
316
+ def prepend_to_pin decl, closure
317
+ pins.push Solargraph::Pin::Reference::Prepend.new(
318
+ name: decl.name.relative!.to_s,
319
+ closure: closure
320
+ )
321
+ end
322
+
323
+ def extend_to_pin decl, closure
324
+ pins.push Solargraph::Pin::Reference::Extend.new(
325
+ name: decl.name.relative!.to_s,
326
+ closure: closure
327
+ )
328
+ end
329
+
330
+ def alias_to_pin decl, closure
331
+ pins.push Solargraph::Pin::MethodAlias.new(
332
+ name: decl.new_name.to_s,
333
+ original: decl.old_name.to_s,
334
+ closure: closure
335
+ )
336
+ end
337
+
338
+ RBS_TO_YARD_TYPE = {
339
+ 'bool' => 'Boolean',
340
+ 'string' => 'String',
341
+ 'int' => 'Integer',
342
+ 'untyped' => '',
343
+ 'NilClass' => 'nil'
344
+ }
345
+
346
+ def method_type_to_tag type
347
+ if type_aliases.key?(type.type.return_type.to_s)
348
+ other_type_to_tag(type_aliases[type.type.return_type.to_s].type)
349
+ else
350
+ other_type_to_tag type.type.return_type
351
+ end
352
+ end
353
+
354
+ # @return [String]
355
+ def other_type_to_tag type
356
+ if type.is_a?(RBS::Types::Optional)
357
+ "#{other_type_to_tag(type.type)}, nil"
358
+ elsif type.is_a?(RBS::Types::Bases::Any)
359
+ # @todo Not sure what to do with Any yet
360
+ 'BasicObject'
361
+ elsif type.is_a?(RBS::Types::Bases::Bool)
362
+ 'Boolean'
363
+ elsif type.is_a?(RBS::Types::Tuple)
364
+ "Array(#{type.types.map { |t| other_type_to_tag(t) }.join(', ')})"
365
+ elsif type.is_a?(RBS::Types::Literal)
366
+ "#{type.literal}"
367
+ elsif type.is_a?(RBS::Types::Union)
368
+ type.types.map { |t| other_type_to_tag(t) }.join(', ')
369
+ elsif type.is_a?(RBS::Types::Record)
370
+ # @todo Better record support
371
+ 'Hash'
372
+ elsif type.is_a?(RBS::Types::Bases::Nil)
373
+ 'nil'
374
+ elsif type.is_a?(RBS::Types::Bases::Self)
375
+ 'self'
376
+ elsif type.is_a?(RBS::Types::Bases::Void)
377
+ 'void'
378
+ elsif type.is_a?(RBS::Types::Variable)
379
+ "param<#{type.name}>"
380
+ elsif type.is_a?(RBS::Types::ClassInstance) #&& !type.args.empty?
381
+ base = RBS_TO_YARD_TYPE[type.name.relative!.to_s] || type.name.relative!.to_s
382
+ params = type.args.map { |a| other_type_to_tag(a) }.reject { |t| t == 'undefined' }
383
+ return base if params.empty?
384
+ "#{base}<#{params.join(', ')}>"
385
+ elsif type.respond_to?(:name) && type.name.respond_to?(:relative!)
386
+ RBS_TO_YARD_TYPE[type.name.relative!.to_s] || type.name.relative!.to_s
387
+ else
388
+ Solargraph.logger.warn "Unrecognized RBS type: #{type.class} #{type}"
389
+ 'undefined'
390
+ end
391
+ end
392
+ end
393
+ end
394
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ class RbsMap
5
+ # Override pins to fill gaps in RbsMap::CoreMap coverage
6
+ #
7
+ module CoreFills
8
+ Override = Pin::Reference::Override
9
+
10
+ KEYWORDS = [
11
+ '__ENCODING__', '__LINE__', '__FILE__', 'BEGIN', 'END', 'alias', 'and',
12
+ 'begin', 'break', 'case', 'class', 'def', 'defined?', 'do', 'else',
13
+ 'elsif', 'end', 'ensure', 'false', 'for', 'if', 'in', 'module', 'next',
14
+ 'nil', 'not', 'or', 'redo', 'rescue', 'retry', 'return', 'self', 'super',
15
+ 'then', 'true', 'undef', 'unless', 'until', 'when', 'while', 'yield'
16
+ ].map { |k| Pin::Keyword.new(k) }
17
+
18
+ YIELDPARAMS = [
19
+ Override.from_comment('Object#tap', %(
20
+ @return [self]
21
+ @yieldparam [self]
22
+ )),
23
+ Override.from_comment('String#each_line', %(
24
+ @yieldparam [String]
25
+ )),
26
+ ]
27
+
28
+ methods_with_yieldparam_subtypes = %w[
29
+ Array#each Array#map Array#map! Array#any? Array#all? Array#index
30
+ Array#keep_if Array#delete_if
31
+ Enumerable#each_entry Enumerable#map Enumerable#any? Enumerable#all?
32
+ Enumerable#select Enumerable#reject
33
+ Set#each
34
+ ]
35
+
36
+ YIELDPARAM_SINGLE_PARAMETERS = methods_with_yieldparam_subtypes.map do |path|
37
+ Override.from_comment(path, %(
38
+ @yieldparam_single_parameter
39
+ ))
40
+ end
41
+
42
+ CLASS_RETURN_TYPES = [
43
+ Override.method_return('Class#new', 'self'),
44
+ Override.method_return('Class.new', 'Class<BasicObject>'),
45
+ Override.method_return('Class#allocate', 'self'),
46
+ Override.method_return('Class.allocate', 'Class<BasicObject>'),
47
+ ]
48
+
49
+ # HACK: Add Errno exception classes
50
+ errno = Solargraph::Pin::Namespace.new(name: 'Errno')
51
+ errnos = []
52
+ Errno.constants.each do |const|
53
+ errnos.push Solargraph::Pin::Namespace.new(type: :class, name: const.to_s, closure: errno)
54
+ errnos.push Solargraph::Pin::Reference::Superclass.new(closure: errnos.last, name: 'SystemCallError')
55
+ end
56
+ ERRNOS = errnos
57
+
58
+ ALL = KEYWORDS + YIELDPARAMS + YIELDPARAM_SINGLE_PARAMETERS + CLASS_RETURN_TYPES + ERRNOS
59
+ end
60
+ end
61
+ end