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.
- checksums.yaml +4 -4
- data/.github/FUNDING.yml +1 -0
- data/.github/workflows/rspec.yml +1 -1
- data/CHANGELOG.md +40 -0
- data/LICENSE +1 -1
- data/README.md +9 -3
- data/SPONSORS.md +4 -4
- data/lib/solargraph/api_map/store.rb +13 -1
- data/lib/solargraph/api_map.rb +30 -12
- data/lib/solargraph/cache.rb +53 -0
- data/lib/solargraph/complex_type/type_methods.rb +10 -6
- data/lib/solargraph/complex_type/unique_type.rb +57 -0
- data/lib/solargraph/complex_type.rb +32 -3
- data/lib/solargraph/convention/rakefile.rb +17 -0
- data/lib/solargraph/convention.rb +2 -0
- data/lib/solargraph/diagnostics/rubocop.rb +17 -3
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +3 -1
- data/lib/solargraph/language_server/host/cataloger.rb +1 -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 +25 -20
- data/lib/solargraph/parser/legacy/node_processors/casgn_node.rb +12 -2
- data/lib/solargraph/parser/legacy/node_processors/sclass_node.rb +24 -3
- data/lib/solargraph/parser/rubyvm/class_methods.rb +6 -1
- data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +13 -2
- 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/sclass_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/base_variable.rb +1 -1
- data/lib/solargraph/pin/conversions.rb +2 -6
- data/lib/solargraph/pin/method.rb +100 -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 +50 -32
- data/lib/solargraph/source/chain/call.rb +35 -24
- data/lib/solargraph/source/chain.rb +22 -7
- data/lib/solargraph/source_map/clip.rb +5 -0
- data/lib/solargraph/source_map/mapper.rb +8 -4
- 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 +35 -194
- data/lib/solargraph.rb +2 -2
- data/solargraph.gemspec +11 -6
- metadata +46 -37
- data/.travis.yml +0 -19
- 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 -140
- data/lib/solargraph/yard_map/stdlib_fills.rb +0 -43
- 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
|
-
|
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 ||=
|
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
|
-
|
123
|
-
|
124
|
-
|
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:
|
172
|
+
name: name,
|
173
|
+
decl: decl,
|
132
174
|
presence: location ? location.range : nil,
|
133
|
-
|
175
|
+
return_type: param_type_from_name(tag, src.first)
|
134
176
|
)
|
135
177
|
end,
|
136
|
-
|
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
|
data/lib/solargraph/pin.rb
CHANGED
@@ -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
|