solargraph 0.48.0 → 0.49.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/FUNDING.yml +1 -0
- data/.github/workflows/rspec.yml +1 -1
- data/CHANGELOG.md +9 -0
- data/LICENSE +1 -1
- data/SPONSORS.md +2 -4
- data/lib/solargraph/api_map/store.rb +13 -1
- data/lib/solargraph/api_map.rb +30 -12
- data/lib/solargraph/cache.rb +51 -0
- data/lib/solargraph/complex_type/type_methods.rb +3 -6
- data/lib/solargraph/complex_type/unique_type.rb +57 -0
- data/lib/solargraph/complex_type.rb +20 -1
- data/lib/solargraph/convention/rakefile.rb +17 -0
- data/lib/solargraph/convention.rb +2 -0
- data/lib/solargraph/diagnostics/rubocop.rb +15 -2
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +3 -1
- data/lib/solargraph/language_server/host.rb +22 -18
- data/lib/solargraph/language_server/message/extended/download_core.rb +1 -5
- data/lib/solargraph/language_server/message/initialize.rb +2 -0
- data/lib/solargraph/language_server/message/text_document/formatting.rb +1 -1
- data/lib/solargraph/language_server/message/text_document/signature_help.rb +1 -6
- data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +10 -3
- data/lib/solargraph/library.rb +21 -20
- data/lib/solargraph/parser/rubyvm/class_methods.rb +6 -1
- data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +20 -8
- data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +14 -3
- data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +4 -2
- data/lib/solargraph/parser/rubyvm/node_wrapper.rb +47 -0
- data/lib/solargraph/pin/base.rb +5 -2
- data/lib/solargraph/pin/conversions.rb +2 -6
- data/lib/solargraph/pin/method.rb +84 -10
- data/lib/solargraph/pin/namespace.rb +4 -1
- data/lib/solargraph/pin/parameter.rb +8 -3
- data/lib/solargraph/pin/signature.rb +23 -0
- data/lib/solargraph/pin.rb +1 -0
- data/lib/solargraph/rbs_map/conversions.rb +394 -0
- data/lib/solargraph/rbs_map/core_fills.rb +61 -0
- data/lib/solargraph/rbs_map/core_map.rb +38 -0
- data/lib/solargraph/rbs_map/core_signs.rb +33 -0
- data/lib/solargraph/rbs_map/stdlib_map.rb +36 -0
- data/lib/solargraph/rbs_map.rb +73 -0
- data/lib/solargraph/shell.rb +38 -30
- data/lib/solargraph/source/chain/call.rb +30 -22
- data/lib/solargraph/source/chain.rb +21 -6
- data/lib/solargraph/source_map/clip.rb +5 -0
- data/lib/solargraph/source_map/mapper.rb +2 -0
- data/lib/solargraph/type_checker.rb +71 -65
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/views/environment.erb +2 -2
- data/lib/solargraph/workspace.rb +11 -14
- data/lib/solargraph/yard_map/mapper/to_method.rb +7 -4
- data/lib/solargraph/yard_map.rb +7 -148
- data/lib/solargraph.rb +2 -2
- data/solargraph.gemspec +8 -6
- metadata +43 -36
- data/lib/solargraph/compat.rb +0 -37
- data/lib/solargraph/yard_map/core_docs.rb +0 -170
- data/lib/solargraph/yard_map/core_fills.rb +0 -208
- data/lib/solargraph/yard_map/core_gen.rb +0 -76
- data/lib/solargraph/yard_map/rdoc_to_yard.rb +0 -143
- data/lib/solargraph/yard_map/stdlib_fills.rb +0 -43
- data/yardoc/2.2.2.tar.gz +0 -0
@@ -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
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Solargraph
|
4
|
+
class RbsMap
|
5
|
+
# Ruby core pins
|
6
|
+
#
|
7
|
+
class CoreMap
|
8
|
+
include Conversions
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
cache = Cache.load('core.ser')
|
12
|
+
if cache
|
13
|
+
pins.replace cache
|
14
|
+
else
|
15
|
+
loader = RBS::EnvironmentLoader.new(repository: RBS::Repository.new(no_stdlib: true))
|
16
|
+
environment = RBS::Environment.from_loader(loader).resolve_type_names
|
17
|
+
environment.declarations.each { |decl| convert_decl_to_pin(decl, Solargraph::Pin::ROOT_PIN) }
|
18
|
+
pins.concat RbsMap::CoreFills::ALL
|
19
|
+
processed = ApiMap::Store.new(pins).pins.reject { |p| p.is_a?(Solargraph::Pin::Reference::Override) }
|
20
|
+
pins.replace processed
|
21
|
+
|
22
|
+
Cache.save('core.ser', pins)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def method_def_to_sigs decl, pin
|
27
|
+
stubs = CoreSigns.sign(pin.path)
|
28
|
+
return super unless stubs
|
29
|
+
stubs.map do |stub|
|
30
|
+
Pin::Signature.new(
|
31
|
+
[],
|
32
|
+
ComplexType.try_parse(stub.return_type)
|
33
|
+
)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Solargraph
|
2
|
+
class RbsMap
|
3
|
+
module CoreSigns
|
4
|
+
Override = Pin::Reference::Override
|
5
|
+
|
6
|
+
class Stub
|
7
|
+
attr_reader :parameters
|
8
|
+
|
9
|
+
attr_reader :return_type
|
10
|
+
|
11
|
+
def initialize parameters, return_type
|
12
|
+
@parameters = parameters
|
13
|
+
@return_type = return_type
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
SIGNATURE_MAP = {
|
18
|
+
'Object#class' => [
|
19
|
+
Stub.new(
|
20
|
+
[],
|
21
|
+
'Class<self>'
|
22
|
+
)
|
23
|
+
]
|
24
|
+
}
|
25
|
+
|
26
|
+
# @param path [String]
|
27
|
+
# @return [Array<Stub>]
|
28
|
+
def self.sign path
|
29
|
+
SIGNATURE_MAP[path]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rbs'
|
4
|
+
require 'set'
|
5
|
+
|
6
|
+
module Solargraph
|
7
|
+
class RbsMap
|
8
|
+
# Ruby stdlib pins
|
9
|
+
#
|
10
|
+
class StdlibMap < RbsMap
|
11
|
+
# @type [Hash{String => RbsMap}]
|
12
|
+
@stdlib_maps_hash = {}
|
13
|
+
|
14
|
+
# @param library [String]
|
15
|
+
def initialize library
|
16
|
+
cache = Cache.load('stdlib', "#{library}.ser")
|
17
|
+
if cache
|
18
|
+
pins.replace cache
|
19
|
+
else
|
20
|
+
super
|
21
|
+
Cache.save('stdlib', "#{library}.ser", pins)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param library [String]
|
26
|
+
# @return [StdlibMap]
|
27
|
+
def self.load library
|
28
|
+
@stdlib_maps_hash[library] ||= StdlibMap.new(library)
|
29
|
+
end
|
30
|
+
|
31
|
+
def repository
|
32
|
+
@repository ||= RBS::Repository.new
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rbs'
|
4
|
+
require 'set'
|
5
|
+
|
6
|
+
module Solargraph
|
7
|
+
class RbsMap
|
8
|
+
autoload :Conversions, 'solargraph/rbs_map/conversions'
|
9
|
+
autoload :CoreMap, 'solargraph/rbs_map/core_map'
|
10
|
+
autoload :CoreFills, 'solargraph/rbs_map/core_fills'
|
11
|
+
autoload :CoreSigns, 'solargraph/rbs_map/core_signs'
|
12
|
+
autoload :StdlibMap, 'solargraph/rbs_map/stdlib_map'
|
13
|
+
|
14
|
+
include Conversions
|
15
|
+
|
16
|
+
# @type [Hash{String => RbsMap}]
|
17
|
+
@@rbs_maps_hash = {}
|
18
|
+
|
19
|
+
attr_reader :library
|
20
|
+
|
21
|
+
# @param library [String]
|
22
|
+
def initialize library
|
23
|
+
@library = library
|
24
|
+
loader = RBS::EnvironmentLoader.new(core_root: nil, repository: repository)
|
25
|
+
add_library loader, library
|
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) }
|
29
|
+
end
|
30
|
+
|
31
|
+
def path_pin path
|
32
|
+
pins.find { |p| p.path == path }
|
33
|
+
end
|
34
|
+
|
35
|
+
def path_pins path
|
36
|
+
pins.select { |p| p.path == path }
|
37
|
+
end
|
38
|
+
|
39
|
+
def resolved?
|
40
|
+
@resolved
|
41
|
+
end
|
42
|
+
|
43
|
+
# @param library [String]
|
44
|
+
# @return [RbsMap]
|
45
|
+
def self.load library
|
46
|
+
@@rbs_maps_hash[library] ||= RbsMap.new(library)
|
47
|
+
end
|
48
|
+
|
49
|
+
def repository
|
50
|
+
@repository ||= RBS::Repository.new(no_stdlib: true)
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
# @param loader [RBS::EnvironmentLoader]
|
56
|
+
# @param library [String]
|
57
|
+
# @return [Boolean] true if adding the library succeeded
|
58
|
+
def add_library loader, library
|
59
|
+
@resolved = if loader.has_library?(library: library, version: nil)
|
60
|
+
loader.add library: library
|
61
|
+
Solargraph.logger.info "#{short_name} successfully loaded library #{library}"
|
62
|
+
true
|
63
|
+
else
|
64
|
+
Solargraph.logger.info "#{short_name} failed to load library #{library}"
|
65
|
+
false
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def short_name
|
70
|
+
self.class.name.split('::').last
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|