ruby-lsp 0.17.5 → 0.17.6
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/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
|