ruby-lsp 0.26.5 → 0.26.7

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.
@@ -1,150 +0,0 @@
1
- # typed: true
2
- # frozen_string_literal: true
3
-
4
- require "test_helper"
5
-
6
- module RubyIndexer
7
- class PrefixTreeTest < Minitest::Test
8
- def test_empty
9
- tree = PrefixTree.new
10
-
11
- assert_empty(tree.search(""))
12
- assert_empty(tree.search("foo"))
13
- end
14
-
15
- def test_single_item
16
- tree = PrefixTree.new
17
- tree.insert("foo", "foo")
18
-
19
- assert_equal(["foo"], tree.search(""))
20
- assert_equal(["foo"], tree.search("foo"))
21
- assert_empty(tree.search("bar"))
22
- end
23
-
24
- def test_multiple_items
25
- tree = PrefixTree.new #: PrefixTree[String]
26
- ["foo", "bar", "baz"].each { |item| tree.insert(item, item) }
27
-
28
- assert_equal(["baz", "bar", "foo"], tree.search(""))
29
- assert_equal(["baz", "bar"], tree.search("b"))
30
- assert_equal(["foo"], tree.search("fo"))
31
- assert_equal(["baz", "bar"], tree.search("ba"))
32
- assert_equal(["baz"], tree.search("baz"))
33
- assert_empty(tree.search("qux"))
34
- end
35
-
36
- def test_multiple_prefixes
37
- tree = PrefixTree.new #: PrefixTree[String]
38
- ["fo", "foo"].each { |item| tree.insert(item, item) }
39
-
40
- assert_equal(["fo", "foo"], tree.search(""))
41
- assert_equal(["fo", "foo"], tree.search("f"))
42
- assert_equal(["fo", "foo"], tree.search("fo"))
43
- assert_equal(["foo"], tree.search("foo"))
44
- assert_empty(tree.search("fooo"))
45
- end
46
-
47
- def test_multiple_prefixes_with_shuffled_order
48
- tree = PrefixTree.new #: PrefixTree[String]
49
- [
50
- "foo/bar/base",
51
- "foo/bar/on",
52
- "foo/bar/support/selection",
53
- "foo/bar/support/runner",
54
- "foo/internal",
55
- "foo/bar/document",
56
- "foo/bar/code",
57
- "foo/bar/support/rails",
58
- "foo/bar/diagnostics",
59
- "foo/bar/document2",
60
- "foo/bar/support/runner2",
61
- "foo/bar/support/diagnostic",
62
- "foo/document",
63
- "foo/bar/formatting",
64
- "foo/bar/support/highlight",
65
- "foo/bar/semantic",
66
- "foo/bar/support/prefix",
67
- "foo/bar/folding",
68
- "foo/bar/selection",
69
- "foo/bar/support/syntax",
70
- "foo/bar/document3",
71
- "foo/bar/hover",
72
- "foo/bar/support/semantic",
73
- "foo/bar/support/source",
74
- "foo/bar/inlay",
75
- "foo/requests",
76
- "foo/bar/support/formatting",
77
- "foo/bar/path",
78
- "foo/executor",
79
- ].each { |item| tree.insert(item, item) }
80
-
81
- assert_equal(
82
- [
83
- "foo/bar/support/formatting",
84
- "foo/bar/support/prefix",
85
- "foo/bar/support/highlight",
86
- "foo/bar/support/diagnostic",
87
- "foo/bar/support/rails",
88
- "foo/bar/support/runner",
89
- "foo/bar/support/runner2",
90
- "foo/bar/support/source",
91
- "foo/bar/support/syntax",
92
- "foo/bar/support/semantic",
93
- "foo/bar/support/selection",
94
- ],
95
- tree.search("foo/bar/support"),
96
- )
97
- end
98
-
99
- def test_deletion
100
- tree = PrefixTree.new #: PrefixTree[String]
101
- ["foo/bar", "foo/baz"].each { |item| tree.insert(item, item) }
102
- assert_equal(["foo/baz", "foo/bar"], tree.search("foo"))
103
-
104
- tree.delete("foo/bar")
105
- assert_empty(tree.search("foo/bar"))
106
- assert_equal(["foo/baz"], tree.search("foo"))
107
- end
108
-
109
- def test_delete_does_not_impact_other_keys_with_the_same_value
110
- tree = PrefixTree.new #: PrefixTree[String]
111
- tree.insert("key1", "value")
112
- tree.insert("key2", "value")
113
- assert_equal(["value", "value"], tree.search("key"))
114
-
115
- tree.delete("key2")
116
- assert_empty(tree.search("key2"))
117
- assert_equal(["value"], tree.search("key1"))
118
- end
119
-
120
- def test_deleted_node_is_removed_from_the_tree
121
- tree = PrefixTree.new #: PrefixTree[String]
122
- tree.insert("foo/bar", "foo/bar")
123
- assert_equal(["foo/bar"], tree.search("foo"))
124
-
125
- tree.delete("foo/bar")
126
- root = tree.instance_variable_get(:@root)
127
- assert_empty(root.children)
128
- end
129
-
130
- def test_deleting_non_terminal_nodes
131
- tree = PrefixTree.new #: PrefixTree[String]
132
- tree.insert("abc", "value1")
133
- tree.insert("abcdef", "value2")
134
-
135
- tree.delete("abcdef")
136
- assert_empty(tree.search("abcdef"))
137
- assert_equal(["value1"], tree.search("abc"))
138
- end
139
-
140
- def test_overriding_values
141
- tree = PrefixTree.new #: PrefixTree[Integer]
142
-
143
- tree.insert("foo/bar", 123)
144
- assert_equal([123], tree.search("foo/bar"))
145
-
146
- tree.insert("foo/bar", 456)
147
- assert_equal([456], tree.search("foo/bar"))
148
- end
149
- end
150
- end
@@ -1,381 +0,0 @@
1
- # typed: true
2
- # frozen_string_literal: true
3
-
4
- require_relative "test_case"
5
-
6
- module RubyIndexer
7
- class RBSIndexerTest < TestCase
8
- def test_index_core_classes
9
- entries = @index["Array"] #: as !nil
10
- refute_nil(entries)
11
- # Array is a class but also an instance method on Kernel
12
- assert_equal(2, entries.length)
13
- entry = entries.find { |entry| entry.is_a?(Entry::Class) } #: as Entry::Class
14
- assert_match(%r{/gems/rbs-.*/core/array.rbs}, entry.file_path)
15
- assert_equal("array.rbs", entry.file_name)
16
- assert_equal("Object", entry.parent_class)
17
- assert_equal(1, entry.mixin_operations.length)
18
- enumerable_include = entry.mixin_operations.first #: as !nil
19
- assert_equal("Enumerable", enumerable_include.module_name)
20
-
21
- # Using fixed positions would be fragile, so let's just check some basics.
22
- assert_operator(entry.location.start_line, :>, 0)
23
- assert_operator(entry.location.end_line, :>, entry.location.start_line)
24
- assert_equal(0, entry.location.start_column)
25
- assert_operator(entry.location.end_column, :>, 0)
26
- end
27
-
28
- def test_index_core_modules
29
- entries = @index["Kernel"] #: as !nil
30
- refute_nil(entries)
31
- assert_equal(2, entries.length)
32
- entry = entries.first #: as Entry::Module
33
- assert_match(%r{/gems/rbs-.*/core/kernel.rbs}, entry.file_path)
34
- assert_equal("kernel.rbs", entry.file_name)
35
-
36
- # Using fixed positions would be fragile, so let's just check some basics.
37
- assert_operator(entry.location.start_line, :>, 0)
38
- assert_operator(entry.location.end_line, :>, entry.location.start_line)
39
- assert_equal(0, entry.location.start_column)
40
- assert_operator(entry.location.end_column, :>, 0)
41
- end
42
-
43
- def test_index_core_constants
44
- entries = @index["RUBY_VERSION"] #: as !nil
45
- refute_nil(entries)
46
- assert_equal(1, entries.length)
47
-
48
- entries = @index["Complex::I"] #: as !nil
49
- refute_nil(entries)
50
- assert_equal(1, entries.length)
51
-
52
- entries = @index["Encoding::US_ASCII"] #: as !nil
53
- refute_nil(entries)
54
- assert_equal(1, entries.length)
55
- end
56
-
57
- def test_index_methods
58
- entries = @index["initialize"] #: as Array[Entry::Method]
59
- refute_nil(entries)
60
- entry = entries.find { |entry| entry.owner&.name == "Array" } #: as Entry::Method
61
- assert_match(%r{/gems/rbs-.*/core/array.rbs}, entry.file_path)
62
- assert_equal("array.rbs", entry.file_name)
63
- assert_equal(:public, entry.visibility)
64
-
65
- # Using fixed positions would be fragile, so let's just check some basics.
66
- assert_operator(entry.location.start_line, :>, 0)
67
- assert_operator(entry.location.end_line, :>, entry.location.start_line)
68
- assert_equal(2, entry.location.start_column)
69
- assert_operator(entry.location.end_column, :>, 0)
70
- end
71
-
72
- def test_index_global_declaration
73
- entries = @index["$DEBUG"] #: as Array[Entry::GlobalVariable]
74
- refute_nil(entries)
75
- assert_equal(1, entries.length)
76
-
77
- entry = entries.first #: as Entry::GlobalVariable
78
-
79
- assert_instance_of(Entry::GlobalVariable, entry)
80
- assert_equal("$DEBUG", entry.name)
81
- assert_match(%r{/gems/rbs-.*/core/global_variables.rbs}, entry.file_path)
82
- assert_operator(entry.location.start_column, :<, entry.location.end_column)
83
- assert_equal(entry.location.start_line, entry.location.end_line)
84
- end
85
-
86
- def test_attaches_correct_owner_to_singleton_methods
87
- entries = @index["basename"] #: as Array[Entry::Method]
88
- refute_nil(entries)
89
-
90
- owner = entries.first&.owner #: as Entry::SingletonClass
91
- assert_instance_of(Entry::SingletonClass, owner)
92
- assert_equal("File::<Class:File>", owner.name)
93
- end
94
-
95
- def test_location_and_name_location_are_the_same
96
- # NOTE: RBS does not store the name location for classes, modules or methods. This behavior is not exactly what
97
- # we would like, but for now we assign the same location to both
98
-
99
- entries = @index["Array"] #: as Array[Entry::Class]
100
- refute_nil(entries)
101
- entry = entries.find { |entry| entry.is_a?(Entry::Class) } #: as Entry::Class
102
-
103
- assert_same(entry.location, entry.name_location)
104
- end
105
-
106
- def test_rbs_method_with_required_positionals
107
- entries = @index["crypt"] #: as Array[Entry::Method]
108
- assert_equal(1, entries.length)
109
-
110
- entry = entries.first #: as Entry::Method
111
- signatures = entry.signatures
112
- assert_equal(1, signatures.length)
113
-
114
- first_signature = signatures.first #: as Entry::Signature
115
-
116
- # (::string salt_str) -> ::String
117
-
118
- assert_equal(1, first_signature.parameters.length)
119
- assert_kind_of(Entry::RequiredParameter, first_signature.parameters[0])
120
- assert_equal(:salt_str, first_signature.parameters[0]&.name)
121
- end
122
-
123
- def test_rbs_method_with_unnamed_required_positionals
124
- entries = @index["try_convert"] #: as Array[Entry::Method]
125
- entry = entries.find { |entry| entry.owner&.name == "Array::<Class:Array>" } #: as Entry::Method
126
-
127
- parameters = entry.signatures[0]&.parameters #: as Array[Entry::Parameter]
128
-
129
- assert_equal([:arg0], parameters.map(&:name))
130
- assert_kind_of(Entry::RequiredParameter, parameters[0])
131
- end
132
-
133
- def test_rbs_method_with_optional_positionals
134
- entries = @index["polar"] #: as Array[Entry::Method]
135
- entry = entries.find { |entry| entry.owner&.name == "Complex::<Class:Complex>" } #: as Entry::Method
136
-
137
- # def self.polar: (Numeric, ?Numeric) -> Complex
138
-
139
- parameters = entry.signatures[0]&.parameters #: as Array[Entry::Parameter]
140
-
141
- assert_equal([:arg0, :arg1], parameters.map(&:name))
142
- assert_kind_of(Entry::RequiredParameter, parameters[0])
143
- assert_kind_of(Entry::OptionalParameter, parameters[1])
144
- end
145
-
146
- def test_rbs_method_with_optional_parameter
147
- entries = @index["chomp"] #: as Array[Entry::Method]
148
- assert_equal(1, entries.length)
149
-
150
- entry = entries.first #: as Entry::Method
151
- signatures = entry.signatures
152
- assert_equal(1, signatures.length)
153
-
154
- first_signature = signatures.first #: as Entry::Signature
155
-
156
- # (?::string? separator) -> ::String
157
-
158
- assert_equal(1, first_signature.parameters.length)
159
- assert_kind_of(Entry::OptionalParameter, first_signature.parameters[0])
160
- assert_equal(:separator, first_signature.parameters[0]&.name)
161
- end
162
-
163
- def test_rbs_method_with_required_and_optional_parameters
164
- entries = @index["gsub"] #: as Array[Entry::Method]
165
- assert_equal(1, entries.length)
166
-
167
- entry = entries.first #: as Entry::Method
168
-
169
- signatures = entry.signatures
170
- assert_equal(3, signatures.length)
171
-
172
- # (::Regexp | ::string pattern, ::string | ::hash[::String, ::_ToS] replacement) -> ::String
173
- # | (::Regexp | ::string pattern) -> ::Enumerator[::String, ::String]
174
- # | (::Regexp | ::string pattern) { (::String match) -> ::_ToS } -> ::String
175
-
176
- parameters = signatures[0]&.parameters #: as !nil
177
- assert_equal([:pattern, :replacement], parameters.map(&:name))
178
- assert_kind_of(Entry::RequiredParameter, parameters[0])
179
- assert_kind_of(Entry::RequiredParameter, parameters[1])
180
-
181
- parameters = signatures[1]&.parameters #: as !nil
182
- assert_equal([:pattern], parameters.map(&:name))
183
- assert_kind_of(Entry::RequiredParameter, parameters[0])
184
-
185
- parameters = signatures[2]&.parameters #: as !nil
186
- assert_equal([:pattern, :"<anonymous block>"], parameters.map(&:name))
187
- assert_kind_of(Entry::RequiredParameter, parameters[0])
188
- assert_kind_of(Entry::BlockParameter, parameters[1])
189
- end
190
-
191
- def test_rbs_anonymous_block_parameter
192
- entries = @index["open"] #: as Array[Entry::Method]
193
- entry = entries.find { |entry| entry.owner&.name == "File::<Class:File>" } #: as Entry::Method
194
-
195
- assert_equal(2, entry.signatures.length)
196
-
197
- # (::String name, ?::String mode, ?::Integer perm) -> ::IO?
198
- # | [T] (::String name, ?::String mode, ?::Integer perm) { (::IO) -> T } -> T
199
-
200
- parameters = entry.signatures[0]&.parameters #: as !nil
201
- assert_equal([:file_name, :mode, :perm], parameters.map(&:name))
202
- assert_kind_of(Entry::RequiredParameter, parameters[0])
203
- assert_kind_of(Entry::OptionalParameter, parameters[1])
204
- assert_kind_of(Entry::OptionalParameter, parameters[2])
205
-
206
- parameters = entry.signatures[1]&.parameters #: as !nil
207
- assert_equal([:file_name, :mode, :perm, :"<anonymous block>"], parameters.map(&:name))
208
- assert_kind_of(Entry::RequiredParameter, parameters[0])
209
- assert_kind_of(Entry::OptionalParameter, parameters[1])
210
- assert_kind_of(Entry::OptionalParameter, parameters[2])
211
- assert_kind_of(Entry::BlockParameter, parameters[3])
212
- end
213
-
214
- def test_rbs_method_with_rest_positionals
215
- entries = @index["count"] #: as Array[Entry::Method]
216
- entry = entries.find { |entry| entry.owner&.name == "String" } #: as Entry::Method
217
-
218
- parameters = entry.signatures.first&.parameters #: as !nil
219
- assert_equal(1, entry.signatures.length)
220
-
221
- # (::String::selector selector_0, *::String::selector more_selectors) -> ::Integer
222
-
223
- assert_equal([:selector_0, :more_selectors], parameters.map(&:name))
224
- assert_kind_of(RubyIndexer::Entry::RequiredParameter, parameters[0])
225
- assert_kind_of(RubyIndexer::Entry::RestParameter, parameters[1])
226
- end
227
-
228
- def test_rbs_method_with_trailing_positionals
229
- entries = @index["select"] #: as Array[Entry::Method]
230
- entry = entries.find { |entry| entry.owner&.name == "IO::<Class:IO>" } #: as !nil
231
-
232
- signatures = entry.signatures
233
- assert_equal(2, signatures.length)
234
-
235
- # 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] ]
236
- # | [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] ]?
237
-
238
- parameters = signatures[0]&.parameters #: as !nil
239
- assert_equal([:read_array, :write_array, :error_array], parameters.map(&:name))
240
- assert_kind_of(Entry::RequiredParameter, parameters[0])
241
- assert_kind_of(Entry::OptionalParameter, parameters[1])
242
- assert_kind_of(Entry::OptionalParameter, parameters[2])
243
-
244
- parameters = signatures[1]&.parameters #: as !nil
245
- assert_equal([:read_array, :write_array, :error_array, :timeout], parameters.map(&:name))
246
- assert_kind_of(Entry::RequiredParameter, parameters[0])
247
- assert_kind_of(Entry::OptionalParameter, parameters[1])
248
- assert_kind_of(Entry::OptionalParameter, parameters[2])
249
- assert_kind_of(Entry::OptionalParameter, parameters[3])
250
- end
251
-
252
- def test_rbs_method_with_optional_keywords
253
- entries = @index["step"] #: as Array[Entry::Method]
254
- entry = entries.find { |entry| entry.owner&.name == "Numeric" } #: as !nil
255
-
256
- signatures = entry.signatures
257
- assert_equal(4, signatures.length)
258
-
259
- # (?::Numeric limit, ?::Numeric step) { (::Numeric) -> void } -> self
260
- # | (?::Numeric limit, ?::Numeric step) -> ::Enumerator[::Numeric, self]
261
- # | (?by: ::Numeric, ?to: ::Numeric) { (::Numeric) -> void } -> self
262
- # | (?by: ::Numeric, ?to: ::Numeric) -> ::Enumerator[::Numeric, self]
263
-
264
- parameters = signatures[0]&.parameters #: as !nil
265
- assert_equal([:limit, :step, :"<anonymous block>"], parameters.map(&:name))
266
- assert_kind_of(Entry::OptionalParameter, parameters[0])
267
- assert_kind_of(Entry::OptionalParameter, parameters[1])
268
- assert_kind_of(Entry::BlockParameter, parameters[2])
269
-
270
- parameters = signatures[1]&.parameters #: as !nil
271
- assert_equal([:limit, :step], parameters.map(&:name))
272
- assert_kind_of(Entry::OptionalParameter, parameters[0])
273
- assert_kind_of(Entry::OptionalParameter, parameters[1])
274
-
275
- parameters = signatures[2]&.parameters #: as !nil
276
- assert_equal([:by, :to, :"<anonymous block>"], parameters.map(&:name))
277
- assert_kind_of(Entry::OptionalKeywordParameter, parameters[0])
278
- assert_kind_of(Entry::OptionalKeywordParameter, parameters[1])
279
- assert_kind_of(Entry::BlockParameter, parameters[2])
280
-
281
- parameters = signatures[3]&.parameters #: as !nil
282
- assert_equal([:by, :to], parameters.map(&:name))
283
- assert_kind_of(Entry::OptionalKeywordParameter, parameters[0])
284
- assert_kind_of(Entry::OptionalKeywordParameter, parameters[1])
285
- end
286
-
287
- def test_rbs_method_with_required_keywords
288
- # There are no methods in Core that have required keyword arguments,
289
- # so we test against RBS directly
290
-
291
- rbs = <<~RBS
292
- class File
293
- def foo: (a: ::Numeric sz, b: ::Numeric) -> void
294
- end
295
- RBS
296
- signatures = parse_rbs_methods(rbs, "foo")
297
- parameters = signatures[0].parameters
298
- assert_equal([:a, :b], parameters.map(&:name))
299
- assert_kind_of(Entry::KeywordParameter, parameters[0])
300
- assert_kind_of(Entry::KeywordParameter, parameters[1])
301
- end
302
-
303
- def test_rbs_method_with_rest_keywords
304
- entries = @index["method_missing"] #: as Array[Entry::Method]
305
- entry = entries.find { |entry| entry.owner&.name == "BasicObject" } #: as !nil
306
- signatures = entry.signatures
307
- assert_equal(1, signatures.length)
308
-
309
- # (Symbol, *untyped, **untyped) ?{ (*untyped, **untyped) -> untyped } -> untyped
310
-
311
- parameters = signatures[0]&.parameters #: as !nil
312
- assert_equal([:arg0, :"<anonymous splat>", :"<anonymous keyword splat>"], parameters.map(&:name))
313
- assert_kind_of(Entry::RequiredParameter, parameters[0])
314
- assert_kind_of(Entry::RestParameter, parameters[1])
315
- assert_kind_of(Entry::KeywordRestParameter, parameters[2])
316
- end
317
-
318
- def test_parse_simple_rbs
319
- rbs = <<~RBS
320
- class File
321
- def self?.open: (String name, ?String mode, ?Integer perm) -> IO?
322
- | [T] (String name, ?String mode, ?Integer perm) { (IO) -> T } -> T
323
- end
324
- RBS
325
- signatures = parse_rbs_methods(rbs, "open")
326
- assert_equal(2, signatures.length)
327
- parameters = signatures[0].parameters
328
- assert_equal([:name, :mode, :perm], parameters.map(&:name))
329
- assert_kind_of(Entry::RequiredParameter, parameters[0])
330
- assert_kind_of(Entry::OptionalParameter, parameters[1])
331
- assert_kind_of(Entry::OptionalParameter, parameters[2])
332
-
333
- parameters = signatures[1].parameters
334
- assert_equal([:name, :mode, :perm, :"<anonymous block>"], parameters.map(&:name))
335
- assert_kind_of(Entry::RequiredParameter, parameters[0])
336
- assert_kind_of(Entry::OptionalParameter, parameters[1])
337
- assert_kind_of(Entry::OptionalParameter, parameters[2])
338
- assert_kind_of(Entry::BlockParameter, parameters[3])
339
- end
340
-
341
- def test_signature_alias
342
- # In RBS, an alias means that two methods have the same signature.
343
- # It does not mean the same thing as a Ruby alias.
344
- any_entries = @index["any?"] #: as Array[Entry::UnresolvedMethodAlias]
345
-
346
- assert_equal(["Array", "Enumerable", "Hash"], any_entries.map { _1.owner&.name })
347
-
348
- entry = any_entries.find { |entry| entry.owner&.name == "Array" } #: as !nil
349
-
350
- assert_kind_of(RubyIndexer::Entry::UnresolvedMethodAlias, entry)
351
- assert_equal("any?", entry.name)
352
- assert_equal("all?", entry.old_name)
353
- assert_equal("Array", entry.owner&.name)
354
- assert(entry.file_path&.end_with?("core/array.rbs"))
355
- refute_empty(entry.comments)
356
- end
357
-
358
- def test_indexing_untyped_functions
359
- entries = @index.resolve_method("call", "Method") #: as Array[Entry::Method]
360
-
361
- parameters = entries.first&.signatures&.first&.parameters #: as !nil
362
- assert_equal(1, parameters.length)
363
- assert_instance_of(Entry::ForwardingParameter, parameters.first)
364
- end
365
-
366
- private
367
-
368
- def parse_rbs_methods(rbs, method_name)
369
- buffer = RBS::Buffer.new(content: rbs, name: "")
370
- _, _, declarations = RBS::Parser.parse_signature(buffer)
371
- index = RubyIndexer::Index.new
372
- indexer = RubyIndexer::RBSIndexer.new(index)
373
- pathname = Pathname.new("/file.rbs")
374
- indexer.process_signature(pathname, declarations)
375
- entry = index[method_name] #: as !nil
376
- .first #: as Entry::Method
377
-
378
- entry.signatures
379
- end
380
- end
381
- end