ruby-lsp 0.17.5 → 0.17.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +8 -0
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +1 -1
- data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +107 -7
- data/lib/ruby_indexer/test/index_test.rb +6 -0
- data/lib/ruby_indexer/test/method_test.rb +37 -24
- data/lib/ruby_indexer/test/rbs_indexer_test.rb +248 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7299237468ae17d80028a1454903f58b1be4ff34428a6c8a538530b5caad54d1
|
4
|
+
data.tar.gz: 26351e5be1671219a9b3624076b2f50fb68c5838303fe1a021eecb39c4e3e9f1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 54cc76a3506a268398cfc51645a70300e2d14bda5b39c12274863270f70ed666b33bfebdf50dac8e013410e8ddba5645f4f435863af795d268710e0ccf9d8814
|
7
|
+
data.tar.gz: 95e52a4aa6f68785495f7435fe54cc395c062809ad3754703f808c68d2599bc34a619578bbb8453cb54de88a8312ac49eff8dd2e72a82bc04554c7b659c477cd
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.17.
|
1
|
+
0.17.6
|
@@ -288,6 +288,14 @@ module RubyIndexer
|
|
288
288
|
class BlockParameter < Parameter
|
289
289
|
DEFAULT_NAME = T.let(:"<anonymous block>", Symbol)
|
290
290
|
|
291
|
+
class << self
|
292
|
+
extend T::Sig
|
293
|
+
sig { returns(BlockParameter) }
|
294
|
+
def anonymous
|
295
|
+
new(name: DEFAULT_NAME)
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
291
299
|
sig { override.returns(Symbol) }
|
292
300
|
def decorated_name
|
293
301
|
:"&#{@name}"
|
@@ -389,7 +389,7 @@ module RubyIndexer
|
|
389
389
|
# If we don't have an entry for `name`, raise
|
390
390
|
entries = self[fully_qualified_name]
|
391
391
|
|
392
|
-
if singleton_levels > 0 && !entries
|
392
|
+
if singleton_levels > 0 && !entries && indexed?(attached_class_name)
|
393
393
|
entries = [existing_or_new_singleton_class(attached_class_name)]
|
394
394
|
end
|
395
395
|
|
@@ -15,20 +15,25 @@ module RubyIndexer
|
|
15
15
|
loader = RBS::EnvironmentLoader.new
|
16
16
|
RBS::Environment.from_loader(loader).resolve_type_names
|
17
17
|
|
18
|
-
loader.each_signature do |
|
19
|
-
process_signature(
|
18
|
+
loader.each_signature do |_source, pathname, _buffer, declarations, _directives|
|
19
|
+
process_signature(pathname, declarations)
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
sig do
|
24
|
+
params(
|
25
|
+
pathname: Pathname,
|
26
|
+
declarations: T::Array[RBS::AST::Declarations::Base],
|
27
|
+
).void
|
28
|
+
end
|
29
|
+
def process_signature(pathname, declarations)
|
27
30
|
declarations.each do |declaration|
|
28
31
|
process_declaration(declaration, pathname)
|
29
32
|
end
|
30
33
|
end
|
31
34
|
|
35
|
+
private
|
36
|
+
|
32
37
|
sig { params(declaration: RBS::AST::Declarations::Base, pathname: Pathname).void }
|
33
38
|
def process_declaration(declaration, pathname)
|
34
39
|
case declaration
|
@@ -122,7 +127,102 @@ module RubyIndexer
|
|
122
127
|
end
|
123
128
|
|
124
129
|
real_owner = member.singleton? ? @index.existing_or_new_singleton_class(owner.name) : owner
|
125
|
-
|
130
|
+
signatures = signatures(member)
|
131
|
+
@index.add(Entry::Method.new(name, file_path, location, location, comments, signatures, visibility, real_owner))
|
132
|
+
end
|
133
|
+
|
134
|
+
sig { params(member: RBS::AST::Members::MethodDefinition).returns(T::Array[Entry::Signature]) }
|
135
|
+
def signatures(member)
|
136
|
+
member.overloads.map do |overload|
|
137
|
+
parameters = process_overload(overload)
|
138
|
+
Entry::Signature.new(parameters)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
sig { params(overload: RBS::AST::Members::MethodDefinition::Overload).returns(T::Array[Entry::Parameter]) }
|
143
|
+
def process_overload(overload)
|
144
|
+
function = T.cast(overload.method_type.type, RBS::Types::Function)
|
145
|
+
parameters = parse_arguments(function)
|
146
|
+
|
147
|
+
block = overload.method_type.block
|
148
|
+
parameters << Entry::BlockParameter.anonymous if block&.required
|
149
|
+
|
150
|
+
parameters
|
151
|
+
end
|
152
|
+
|
153
|
+
sig { params(function: RBS::Types::Function).returns(T::Array[Entry::Parameter]) }
|
154
|
+
def parse_arguments(function)
|
155
|
+
parameters = []
|
156
|
+
parameters.concat(process_required_and_optional_positionals(function))
|
157
|
+
parameters.concat(process_trailing_positionals(function)) if function.trailing_positionals
|
158
|
+
parameters << process_rest_positionals(function) if function.rest_positionals
|
159
|
+
parameters.concat(process_required_keywords(function)) if function.required_keywords
|
160
|
+
parameters.concat(process_optional_keywords(function)) if function.optional_keywords
|
161
|
+
parameters << process_rest_keywords(function) if function.rest_keywords
|
162
|
+
parameters
|
163
|
+
end
|
164
|
+
|
165
|
+
sig { params(function: RBS::Types::Function).returns(T::Array[Entry::RequiredParameter]) }
|
166
|
+
def process_required_and_optional_positionals(function)
|
167
|
+
argument_offset = 0
|
168
|
+
|
169
|
+
required = function.required_positionals.map.with_index(argument_offset) do |param, i|
|
170
|
+
# Some parameters don't have names, e.g.
|
171
|
+
# def self.try_convert: [U] (untyped) -> ::Array[U]?
|
172
|
+
name = param.name || :"arg#{i}"
|
173
|
+
argument_offset += 1
|
174
|
+
|
175
|
+
Entry::RequiredParameter.new(name: name)
|
176
|
+
end
|
177
|
+
|
178
|
+
optional = function.optional_positionals.map.with_index(argument_offset) do |param, i|
|
179
|
+
# Optional positionals may be unnamed, e.g.
|
180
|
+
# def self.polar: (Numeric, ?Numeric) -> Complex
|
181
|
+
name = param.name || :"arg#{i}"
|
182
|
+
|
183
|
+
Entry::OptionalParameter.new(name: name)
|
184
|
+
end
|
185
|
+
|
186
|
+
required + optional
|
187
|
+
end
|
188
|
+
|
189
|
+
sig { params(function: RBS::Types::Function).returns(T::Array[Entry::OptionalParameter]) }
|
190
|
+
def process_trailing_positionals(function)
|
191
|
+
function.trailing_positionals.map do |param|
|
192
|
+
Entry::OptionalParameter.new(name: param.name)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
sig { params(function: RBS::Types::Function).returns(Entry::RestParameter) }
|
197
|
+
def process_rest_positionals(function)
|
198
|
+
rest = function.rest_positionals
|
199
|
+
|
200
|
+
rest_name = rest.name || Entry::RestParameter::DEFAULT_NAME
|
201
|
+
|
202
|
+
Entry::RestParameter.new(name: rest_name)
|
203
|
+
end
|
204
|
+
|
205
|
+
sig { params(function: RBS::Types::Function).returns(T::Array[Entry::KeywordParameter]) }
|
206
|
+
def process_required_keywords(function)
|
207
|
+
function.required_keywords.map do |name, _param|
|
208
|
+
Entry::KeywordParameter.new(name: name)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
sig { params(function: RBS::Types::Function).returns(T::Array[Entry::OptionalKeywordParameter]) }
|
213
|
+
def process_optional_keywords(function)
|
214
|
+
function.optional_keywords.map do |name, _param|
|
215
|
+
Entry::OptionalKeywordParameter.new(name: name)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
sig { params(function: RBS::Types::Function).returns(Entry::KeywordRestParameter) }
|
220
|
+
def process_rest_keywords(function)
|
221
|
+
param = function.rest_keywords
|
222
|
+
|
223
|
+
name = param.name || Entry::KeywordRestParameter::DEFAULT_NAME
|
224
|
+
|
225
|
+
Entry::KeywordRestParameter.new(name: name)
|
126
226
|
end
|
127
227
|
end
|
128
228
|
end
|
@@ -1707,5 +1707,11 @@ module RubyIndexer
|
|
1707
1707
|
@index.linearized_ancestors_of("A::<Class:A>"),
|
1708
1708
|
)
|
1709
1709
|
end
|
1710
|
+
|
1711
|
+
def test_linearizing_a_singleton_class_with_no_attached
|
1712
|
+
assert_raises(Index::NonExistingNamespaceError) do
|
1713
|
+
@index.linearized_ancestors_of("A::<Class:A>")
|
1714
|
+
end
|
1715
|
+
end
|
1710
1716
|
end
|
1711
1717
|
end
|
@@ -123,8 +123,9 @@ module RubyIndexer
|
|
123
123
|
|
124
124
|
assert_entry("bar", Entry::Method, "/fake/path/foo.rb:1-2:2-5")
|
125
125
|
entry = T.must(@index["bar"].first)
|
126
|
-
|
127
|
-
|
126
|
+
parameters = entry.signatures.first.parameters
|
127
|
+
assert_equal(1, parameters.length)
|
128
|
+
parameter = parameters.first
|
128
129
|
assert_equal(:a, parameter.name)
|
129
130
|
assert_instance_of(Entry::RequiredParameter, parameter)
|
130
131
|
end
|
@@ -139,8 +140,9 @@ module RubyIndexer
|
|
139
140
|
|
140
141
|
assert_entry("bar", Entry::Method, "/fake/path/foo.rb:1-2:2-5")
|
141
142
|
entry = T.must(@index["bar"].first)
|
142
|
-
|
143
|
-
|
143
|
+
parameters = entry.signatures.first.parameters
|
144
|
+
assert_equal(1, parameters.length)
|
145
|
+
parameter = parameters.first
|
144
146
|
assert_equal(:"(a, (b, ))", parameter.name)
|
145
147
|
assert_instance_of(Entry::RequiredParameter, parameter)
|
146
148
|
end
|
@@ -155,8 +157,9 @@ module RubyIndexer
|
|
155
157
|
|
156
158
|
assert_entry("bar", Entry::Method, "/fake/path/foo.rb:1-2:2-5")
|
157
159
|
entry = T.must(@index["bar"].first)
|
158
|
-
|
159
|
-
|
160
|
+
parameters = entry.signatures.first.parameters
|
161
|
+
assert_equal(1, parameters.length)
|
162
|
+
parameter = parameters.first
|
160
163
|
assert_equal(:a, parameter.name)
|
161
164
|
assert_instance_of(Entry::OptionalParameter, parameter)
|
162
165
|
end
|
@@ -171,8 +174,9 @@ module RubyIndexer
|
|
171
174
|
|
172
175
|
assert_entry("bar", Entry::Method, "/fake/path/foo.rb:1-2:2-5")
|
173
176
|
entry = T.must(@index["bar"].first)
|
174
|
-
|
175
|
-
|
177
|
+
parameters = entry.signatures.first.parameters
|
178
|
+
assert_equal(2, parameters.length)
|
179
|
+
a, b = parameters
|
176
180
|
|
177
181
|
assert_equal(:a, a.name)
|
178
182
|
assert_instance_of(Entry::KeywordParameter, a)
|
@@ -191,8 +195,9 @@ module RubyIndexer
|
|
191
195
|
|
192
196
|
assert_entry("bar", Entry::Method, "/fake/path/foo.rb:1-2:2-5")
|
193
197
|
entry = T.must(@index["bar"].first)
|
194
|
-
|
195
|
-
|
198
|
+
parameters = entry.signatures.first.parameters
|
199
|
+
assert_equal(2, parameters.length)
|
200
|
+
a, b = parameters
|
196
201
|
|
197
202
|
assert_equal(:a, a.name)
|
198
203
|
assert_instance_of(Entry::RestParameter, a)
|
@@ -216,8 +221,9 @@ module RubyIndexer
|
|
216
221
|
|
217
222
|
assert_entry("bar", Entry::Method, "/fake/path/foo.rb:1-2:2-5")
|
218
223
|
entry = T.must(@index["bar"].first)
|
219
|
-
|
220
|
-
|
224
|
+
parameters = entry.signatures.first.parameters
|
225
|
+
assert_equal(2, parameters.length)
|
226
|
+
a, b = parameters
|
221
227
|
|
222
228
|
assert_equal(:a, a.name)
|
223
229
|
assert_instance_of(Entry::RestParameter, a)
|
@@ -226,8 +232,9 @@ module RubyIndexer
|
|
226
232
|
assert_instance_of(Entry::RequiredParameter, b)
|
227
233
|
|
228
234
|
entry = T.must(@index["baz"].first)
|
229
|
-
|
230
|
-
|
235
|
+
parameters = entry.signatures.first.parameters
|
236
|
+
assert_equal(2, parameters.length)
|
237
|
+
a, b = parameters
|
231
238
|
|
232
239
|
assert_equal(:a, a.name)
|
233
240
|
assert_instance_of(Entry::KeywordRestParameter, a)
|
@@ -236,8 +243,9 @@ module RubyIndexer
|
|
236
243
|
assert_instance_of(Entry::RequiredParameter, b)
|
237
244
|
|
238
245
|
entry = T.must(@index["qux"].first)
|
239
|
-
|
240
|
-
|
246
|
+
parameters = entry.signatures.first.parameters
|
247
|
+
assert_equal(2, parameters.length)
|
248
|
+
_a, second = parameters
|
241
249
|
|
242
250
|
assert_equal(:"(b, c)", second.name)
|
243
251
|
assert_instance_of(Entry::RequiredParameter, second)
|
@@ -253,8 +261,9 @@ module RubyIndexer
|
|
253
261
|
|
254
262
|
assert_entry("bar", Entry::Method, "/fake/path/foo.rb:1-2:2-5")
|
255
263
|
entry = T.must(@index["bar"].first)
|
256
|
-
|
257
|
-
|
264
|
+
parameters = entry.signatures.first.parameters
|
265
|
+
assert_equal(1, parameters.length)
|
266
|
+
param = parameters.first
|
258
267
|
|
259
268
|
assert_equal(:"(a, *b)", param.name)
|
260
269
|
assert_instance_of(Entry::RequiredParameter, param)
|
@@ -272,14 +281,16 @@ module RubyIndexer
|
|
272
281
|
RUBY
|
273
282
|
|
274
283
|
entry = T.must(@index["bar"].first)
|
275
|
-
|
284
|
+
parameters = entry.signatures.first.parameters
|
285
|
+
param = parameters.first
|
276
286
|
assert_equal(:block, param.name)
|
277
287
|
assert_instance_of(Entry::BlockParameter, param)
|
278
288
|
|
279
289
|
entry = T.must(@index["baz"].first)
|
280
|
-
|
290
|
+
parameters = entry.signatures.first.parameters
|
291
|
+
assert_equal(1, parameters.length)
|
281
292
|
|
282
|
-
param =
|
293
|
+
param = parameters.first
|
283
294
|
assert_equal(Entry::BlockParameter::DEFAULT_NAME, param.name)
|
284
295
|
assert_instance_of(Entry::BlockParameter, param)
|
285
296
|
end
|
@@ -294,8 +305,9 @@ module RubyIndexer
|
|
294
305
|
|
295
306
|
assert_entry("bar", Entry::Method, "/fake/path/foo.rb:1-2:2-5")
|
296
307
|
entry = T.must(@index["bar"].first)
|
297
|
-
|
298
|
-
|
308
|
+
parameters = entry.signatures.first.parameters
|
309
|
+
assert_equal(2, parameters.length)
|
310
|
+
first, second = parameters
|
299
311
|
|
300
312
|
assert_equal(Entry::RestParameter::DEFAULT_NAME, first.name)
|
301
313
|
assert_instance_of(Entry::RestParameter, first)
|
@@ -314,7 +326,8 @@ module RubyIndexer
|
|
314
326
|
|
315
327
|
assert_entry("bar", Entry::Method, "/fake/path/foo.rb:1-2:2-5")
|
316
328
|
entry = T.must(@index["bar"].first)
|
317
|
-
|
329
|
+
parameters = entry.signatures.first.parameters
|
330
|
+
assert_empty(parameters)
|
318
331
|
end
|
319
332
|
|
320
333
|
def test_keeps_track_of_method_owner
|
@@ -74,5 +74,253 @@ module RubyIndexer
|
|
74
74
|
|
75
75
|
assert_same(entry.location, entry.name_location)
|
76
76
|
end
|
77
|
+
|
78
|
+
def test_rbs_method_with_required_positionals
|
79
|
+
entries = @index["crypt"]
|
80
|
+
assert_equal(1, entries.length)
|
81
|
+
|
82
|
+
entry = entries.first
|
83
|
+
signatures = entry.signatures
|
84
|
+
assert_equal(1, signatures.length)
|
85
|
+
|
86
|
+
first_signature = signatures.first
|
87
|
+
|
88
|
+
# (::string salt_str) -> ::String
|
89
|
+
|
90
|
+
assert_equal(1, first_signature.parameters.length)
|
91
|
+
assert_kind_of(Entry::RequiredParameter, first_signature.parameters[0])
|
92
|
+
assert_equal(:salt_str, first_signature.parameters[0].name)
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_rbs_method_with_unnamed_required_positionals
|
96
|
+
entries = @index["try_convert"]
|
97
|
+
entry = entries.find { |entry| entry.owner.name == "Array::<Class:Array>" }
|
98
|
+
|
99
|
+
parameters = entry.signatures[0].parameters
|
100
|
+
|
101
|
+
assert_equal([:arg0], parameters.map(&:name))
|
102
|
+
assert_kind_of(Entry::RequiredParameter, parameters[0])
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_rbs_method_with_optional_positionals
|
106
|
+
entries = @index["polar"]
|
107
|
+
entry = entries.find { |entry| entry.owner.name == "Complex::<Class:Complex>" }
|
108
|
+
|
109
|
+
# def self.polar: (Numeric, ?Numeric) -> Complex
|
110
|
+
|
111
|
+
parameters = entry.signatures[0].parameters
|
112
|
+
|
113
|
+
assert_equal([:arg0, :arg1], parameters.map(&:name))
|
114
|
+
assert_kind_of(Entry::RequiredParameter, parameters[0])
|
115
|
+
assert_kind_of(Entry::OptionalParameter, parameters[1])
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_rbs_method_with_optional_parameter
|
119
|
+
entries = @index["chomp"]
|
120
|
+
assert_equal(1, entries.length)
|
121
|
+
|
122
|
+
entry = entries.first
|
123
|
+
signatures = entry.signatures
|
124
|
+
assert_equal(1, signatures.length)
|
125
|
+
|
126
|
+
first_signature = signatures.first
|
127
|
+
|
128
|
+
# (?::string? separator) -> ::String
|
129
|
+
|
130
|
+
assert_equal(1, first_signature.parameters.length)
|
131
|
+
assert_kind_of(Entry::OptionalParameter, first_signature.parameters[0])
|
132
|
+
assert_equal(:separator, first_signature.parameters[0].name)
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_rbs_method_with_required_and_optional_parameters
|
136
|
+
entries = @index["gsub"]
|
137
|
+
assert_equal(1, entries.length)
|
138
|
+
|
139
|
+
entry = entries.first
|
140
|
+
|
141
|
+
signatures = entry.signatures
|
142
|
+
assert_equal(3, signatures.length)
|
143
|
+
|
144
|
+
# (::Regexp | ::string pattern, ::string | ::hash[::String, ::_ToS] replacement) -> ::String
|
145
|
+
# | (::Regexp | ::string pattern) -> ::Enumerator[::String, ::String]
|
146
|
+
# | (::Regexp | ::string pattern) { (::String match) -> ::_ToS } -> ::String
|
147
|
+
|
148
|
+
parameters = signatures[0].parameters
|
149
|
+
assert_equal([:pattern, :replacement], parameters.map(&:name))
|
150
|
+
assert_kind_of(Entry::RequiredParameter, parameters[0])
|
151
|
+
assert_kind_of(Entry::RequiredParameter, parameters[1])
|
152
|
+
|
153
|
+
parameters = signatures[1].parameters
|
154
|
+
assert_equal([:pattern], parameters.map(&:name))
|
155
|
+
assert_kind_of(Entry::RequiredParameter, parameters[0])
|
156
|
+
|
157
|
+
parameters = signatures[2].parameters
|
158
|
+
assert_equal([:pattern, :"<anonymous block>"], parameters.map(&:name))
|
159
|
+
assert_kind_of(Entry::RequiredParameter, parameters[0])
|
160
|
+
assert_kind_of(Entry::BlockParameter, parameters[1])
|
161
|
+
end
|
162
|
+
|
163
|
+
def test_rbs_anonymous_block_parameter
|
164
|
+
entries = @index["open"]
|
165
|
+
entry = entries.find { |entry| entry.owner.name == "File::<Class:File>" }
|
166
|
+
|
167
|
+
assert_equal(2, entry.signatures.length)
|
168
|
+
|
169
|
+
# (::String name, ?::String mode, ?::Integer perm) -> ::IO?
|
170
|
+
# | [T] (::String name, ?::String mode, ?::Integer perm) { (::IO) -> T } -> T
|
171
|
+
|
172
|
+
parameters = entry.signatures[0].parameters
|
173
|
+
assert_equal([:file_name, :mode, :perm], parameters.map(&:name))
|
174
|
+
assert_kind_of(Entry::RequiredParameter, parameters[0])
|
175
|
+
assert_kind_of(Entry::OptionalParameter, parameters[1])
|
176
|
+
assert_kind_of(Entry::OptionalParameter, parameters[2])
|
177
|
+
|
178
|
+
parameters = entry.signatures[1].parameters
|
179
|
+
assert_equal([:file_name, :mode, :perm, :"<anonymous block>"], parameters.map(&:name))
|
180
|
+
assert_kind_of(Entry::RequiredParameter, parameters[0])
|
181
|
+
assert_kind_of(Entry::OptionalParameter, parameters[1])
|
182
|
+
assert_kind_of(Entry::OptionalParameter, parameters[2])
|
183
|
+
assert_kind_of(Entry::BlockParameter, parameters[3])
|
184
|
+
end
|
185
|
+
|
186
|
+
def test_rbs_method_with_rest_positionals
|
187
|
+
entries = @index["count"]
|
188
|
+
entry = entries.find { |entry| entry.owner.name == "String" }
|
189
|
+
|
190
|
+
parameters = entry.signatures.first.parameters
|
191
|
+
assert_equal(1, entry.signatures.length)
|
192
|
+
|
193
|
+
# (::String::selector selector_0, *::String::selector more_selectors) -> ::Integer
|
194
|
+
|
195
|
+
assert_equal([:selector_0, :more_selectors], parameters.map(&:name))
|
196
|
+
assert_kind_of(RubyIndexer::Entry::RequiredParameter, parameters[0])
|
197
|
+
assert_kind_of(RubyIndexer::Entry::RestParameter, parameters[1])
|
198
|
+
end
|
199
|
+
|
200
|
+
def test_rbs_method_with_trailing_positionals
|
201
|
+
entries = @index["select"] # https://ruby-doc.org/3.3.3/IO.html#method-c-select
|
202
|
+
entry = entries.find { |entry| entry.owner.name == "IO::<Class:IO>" }
|
203
|
+
|
204
|
+
signatures = entry.signatures
|
205
|
+
assert_equal(2, signatures.length)
|
206
|
+
|
207
|
+
# def self.select: [X, Y, Z] (::Array[X & io]? read_array, ?::Array[Y & io]? write_array, ?::Array[Z & io]? error_array) -> [ Array[X], Array[Y], Array[Z] ] # rubocop:disable Layout/LineLength
|
208
|
+
# | [X, Y, Z] (::Array[X & io]? read_array, ?::Array[Y & io]? write_array, ?::Array[Z & io]? error_array, Time::_Timeout? timeout) -> [ Array[X], Array[Y], Array[Z] ]? # rubocop:disable Layout/LineLength
|
209
|
+
|
210
|
+
parameters = signatures[0].parameters
|
211
|
+
assert_equal([:read_array, :write_array, :error_array], parameters.map(&:name))
|
212
|
+
assert_kind_of(Entry::RequiredParameter, parameters[0])
|
213
|
+
assert_kind_of(Entry::OptionalParameter, parameters[1])
|
214
|
+
assert_kind_of(Entry::OptionalParameter, parameters[2])
|
215
|
+
|
216
|
+
parameters = signatures[1].parameters
|
217
|
+
assert_equal([:read_array, :write_array, :error_array, :timeout], parameters.map(&:name))
|
218
|
+
assert_kind_of(Entry::RequiredParameter, parameters[0])
|
219
|
+
assert_kind_of(Entry::OptionalParameter, parameters[1])
|
220
|
+
assert_kind_of(Entry::OptionalParameter, parameters[2])
|
221
|
+
assert_kind_of(Entry::OptionalParameter, parameters[3])
|
222
|
+
end
|
223
|
+
|
224
|
+
def test_rbs_method_with_optional_keywords
|
225
|
+
entries = @index["step"]
|
226
|
+
entry = entries.find { |entry| entry.owner.name == "Numeric" }
|
227
|
+
|
228
|
+
signatures = entry.signatures
|
229
|
+
assert_equal(4, signatures.length)
|
230
|
+
|
231
|
+
# (?::Numeric limit, ?::Numeric step) { (::Numeric) -> void } -> self
|
232
|
+
# | (?::Numeric limit, ?::Numeric step) -> ::Enumerator[::Numeric, self]
|
233
|
+
# | (?by: ::Numeric, ?to: ::Numeric) { (::Numeric) -> void } -> self
|
234
|
+
# | (?by: ::Numeric, ?to: ::Numeric) -> ::Enumerator[::Numeric, self]
|
235
|
+
|
236
|
+
parameters = signatures[0].parameters
|
237
|
+
assert_equal([:limit, :step, :"<anonymous block>"], parameters.map(&:name))
|
238
|
+
assert_kind_of(Entry::OptionalParameter, parameters[0])
|
239
|
+
assert_kind_of(Entry::OptionalParameter, parameters[1])
|
240
|
+
assert_kind_of(Entry::BlockParameter, parameters[2])
|
241
|
+
|
242
|
+
parameters = signatures[1].parameters
|
243
|
+
assert_equal([:limit, :step], parameters.map(&:name))
|
244
|
+
assert_kind_of(Entry::OptionalParameter, parameters[0])
|
245
|
+
assert_kind_of(Entry::OptionalParameter, parameters[1])
|
246
|
+
|
247
|
+
parameters = signatures[2].parameters
|
248
|
+
assert_equal([:by, :to, :"<anonymous block>"], parameters.map(&:name))
|
249
|
+
assert_kind_of(Entry::OptionalKeywordParameter, parameters[0])
|
250
|
+
assert_kind_of(Entry::OptionalKeywordParameter, parameters[1])
|
251
|
+
assert_kind_of(Entry::BlockParameter, parameters[2])
|
252
|
+
|
253
|
+
parameters = signatures[3].parameters
|
254
|
+
assert_equal([:by, :to], parameters.map(&:name))
|
255
|
+
assert_kind_of(Entry::OptionalKeywordParameter, parameters[0])
|
256
|
+
assert_kind_of(Entry::OptionalKeywordParameter, parameters[1])
|
257
|
+
end
|
258
|
+
|
259
|
+
def test_rbs_method_with_required_keywords
|
260
|
+
# There are no methods in Core that have required keyword arguments,
|
261
|
+
# so we test against RBS directly
|
262
|
+
|
263
|
+
rbs = <<~RBS
|
264
|
+
class File
|
265
|
+
def foo: (a: ::Numeric sz, b: ::Numeric) -> void
|
266
|
+
end
|
267
|
+
RBS
|
268
|
+
signatures = parse_rbs_methods(rbs, "foo")
|
269
|
+
parameters = signatures[0].parameters
|
270
|
+
assert_equal([:a, :b], parameters.map(&:name))
|
271
|
+
assert_kind_of(Entry::KeywordParameter, parameters[0])
|
272
|
+
assert_kind_of(Entry::KeywordParameter, parameters[1])
|
273
|
+
end
|
274
|
+
|
275
|
+
def test_rbs_method_with_rest_keywords
|
276
|
+
entries = @index["method_missing"]
|
277
|
+
entry = entries.find { |entry| entry.owner.name == "BasicObject" }
|
278
|
+
signatures = entry.signatures
|
279
|
+
assert_equal(1, signatures.length)
|
280
|
+
|
281
|
+
# (Symbol, *untyped, **untyped) ?{ (*untyped, **untyped) -> untyped } -> untyped
|
282
|
+
|
283
|
+
parameters = signatures[0].parameters
|
284
|
+
assert_equal([:arg0, :"<anonymous splat>", :"<anonymous keyword splat>"], parameters.map(&:name))
|
285
|
+
assert_kind_of(Entry::RequiredParameter, parameters[0])
|
286
|
+
assert_kind_of(Entry::RestParameter, parameters[1])
|
287
|
+
assert_kind_of(Entry::KeywordRestParameter, parameters[2])
|
288
|
+
end
|
289
|
+
|
290
|
+
def test_parse_simple_rbs
|
291
|
+
rbs = <<~RBS
|
292
|
+
class File
|
293
|
+
def self?.open: (String name, ?String mode, ?Integer perm) -> IO?
|
294
|
+
| [T] (String name, ?String mode, ?Integer perm) { (IO) -> T } -> T
|
295
|
+
end
|
296
|
+
RBS
|
297
|
+
signatures = parse_rbs_methods(rbs, "open")
|
298
|
+
assert_equal(2, signatures.length)
|
299
|
+
parameters = signatures[0].parameters
|
300
|
+
assert_equal([:name, :mode, :perm], parameters.map(&:name))
|
301
|
+
assert_kind_of(Entry::RequiredParameter, parameters[0])
|
302
|
+
assert_kind_of(Entry::OptionalParameter, parameters[1])
|
303
|
+
assert_kind_of(Entry::OptionalParameter, parameters[2])
|
304
|
+
|
305
|
+
parameters = signatures[1].parameters
|
306
|
+
assert_equal([:name, :mode, :perm, :"<anonymous block>"], parameters.map(&:name))
|
307
|
+
assert_kind_of(Entry::RequiredParameter, parameters[0])
|
308
|
+
assert_kind_of(Entry::OptionalParameter, parameters[1])
|
309
|
+
assert_kind_of(Entry::OptionalParameter, parameters[2])
|
310
|
+
assert_kind_of(Entry::BlockParameter, parameters[3])
|
311
|
+
end
|
312
|
+
|
313
|
+
private
|
314
|
+
|
315
|
+
def parse_rbs_methods(rbs, method_name)
|
316
|
+
buffer = RBS::Buffer.new(content: rbs, name: "")
|
317
|
+
_, _, declarations = RBS::Parser.parse_signature(buffer)
|
318
|
+
index = RubyIndexer::Index.new
|
319
|
+
indexer = RubyIndexer::RBSIndexer.new(index)
|
320
|
+
pathname = Pathname.new("file.rbs")
|
321
|
+
indexer.process_signature(pathname, declarations)
|
322
|
+
entry = T.must(index[method_name]).first
|
323
|
+
T.cast(entry, Entry::Method).signatures
|
324
|
+
end
|
77
325
|
end
|
78
326
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-lsp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.17.
|
4
|
+
version: 0.17.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shopify
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-07-
|
11
|
+
date: 2024-07-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: language_server-protocol
|