ruby-lsp 0.23.11 → 0.23.17

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.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/VERSION +1 -1
  4. data/exe/ruby-lsp-launcher +20 -11
  5. data/lib/rubocop/cop/ruby_lsp/use_language_server_aliases.rb +1 -1
  6. data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +3 -5
  7. data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +82 -116
  8. data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +134 -183
  9. data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +9 -10
  10. data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +97 -217
  11. data/lib/ruby_indexer/lib/ruby_indexer/index.rb +139 -281
  12. data/lib/ruby_indexer/lib/ruby_indexer/location.rb +4 -27
  13. data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +18 -19
  14. data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +23 -55
  15. data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +47 -61
  16. data/lib/ruby_indexer/lib/ruby_indexer/uri.rb +17 -19
  17. data/lib/ruby_indexer/lib/ruby_indexer/visibility_scope.rb +7 -11
  18. data/lib/ruby_indexer/test/class_variables_test.rb +14 -14
  19. data/lib/ruby_indexer/test/classes_and_modules_test.rb +65 -40
  20. data/lib/ruby_indexer/test/configuration_test.rb +48 -7
  21. data/lib/ruby_indexer/test/constant_test.rb +34 -34
  22. data/lib/ruby_indexer/test/enhancements_test.rb +1 -1
  23. data/lib/ruby_indexer/test/index_test.rb +146 -135
  24. data/lib/ruby_indexer/test/instance_variables_test.rb +37 -37
  25. data/lib/ruby_indexer/test/method_test.rb +149 -123
  26. data/lib/ruby_indexer/test/prefix_tree_test.rb +13 -13
  27. data/lib/ruby_indexer/test/rbs_indexer_test.rb +68 -73
  28. data/lib/ruby_indexer/test/test_case.rb +9 -3
  29. data/lib/ruby_indexer/test/uri_test.rb +15 -2
  30. data/lib/ruby_lsp/addon.rb +44 -71
  31. data/lib/ruby_lsp/base_server.rb +29 -32
  32. data/lib/ruby_lsp/client_capabilities.rb +10 -12
  33. data/lib/ruby_lsp/document.rb +40 -54
  34. data/lib/ruby_lsp/erb_document.rb +37 -41
  35. data/lib/ruby_lsp/global_state.rb +52 -57
  36. data/lib/ruby_lsp/internal.rb +2 -0
  37. data/lib/ruby_lsp/listeners/code_lens.rb +82 -89
  38. data/lib/ruby_lsp/listeners/completion.rb +67 -73
  39. data/lib/ruby_lsp/listeners/definition.rb +44 -58
  40. data/lib/ruby_lsp/listeners/document_highlight.rb +123 -150
  41. data/lib/ruby_lsp/listeners/document_link.rb +50 -70
  42. data/lib/ruby_lsp/listeners/document_symbol.rb +38 -52
  43. data/lib/ruby_lsp/listeners/folding_ranges.rb +40 -43
  44. data/lib/ruby_lsp/listeners/hover.rb +92 -110
  45. data/lib/ruby_lsp/listeners/inlay_hints.rb +4 -11
  46. data/lib/ruby_lsp/listeners/semantic_highlighting.rb +54 -56
  47. data/lib/ruby_lsp/listeners/signature_help.rb +12 -27
  48. data/lib/ruby_lsp/listeners/spec_style.rb +155 -0
  49. data/lib/ruby_lsp/listeners/test_discovery.rb +89 -0
  50. data/lib/ruby_lsp/listeners/test_style.rb +167 -90
  51. data/lib/ruby_lsp/node_context.rb +12 -39
  52. data/lib/ruby_lsp/rbs_document.rb +9 -7
  53. data/lib/ruby_lsp/requests/code_action_resolve.rb +63 -59
  54. data/lib/ruby_lsp/requests/code_actions.rb +14 -26
  55. data/lib/ruby_lsp/requests/code_lens.rb +20 -19
  56. data/lib/ruby_lsp/requests/completion.rb +7 -20
  57. data/lib/ruby_lsp/requests/completion_resolve.rb +6 -6
  58. data/lib/ruby_lsp/requests/definition.rb +7 -17
  59. data/lib/ruby_lsp/requests/diagnostics.rb +8 -11
  60. data/lib/ruby_lsp/requests/discover_tests.rb +18 -5
  61. data/lib/ruby_lsp/requests/document_highlight.rb +5 -15
  62. data/lib/ruby_lsp/requests/document_link.rb +6 -17
  63. data/lib/ruby_lsp/requests/document_symbol.rb +5 -8
  64. data/lib/ruby_lsp/requests/folding_ranges.rb +7 -15
  65. data/lib/ruby_lsp/requests/formatting.rb +6 -9
  66. data/lib/ruby_lsp/requests/go_to_relevant_file.rb +85 -0
  67. data/lib/ruby_lsp/requests/hover.rb +10 -20
  68. data/lib/ruby_lsp/requests/inlay_hints.rb +6 -17
  69. data/lib/ruby_lsp/requests/on_type_formatting.rb +32 -40
  70. data/lib/ruby_lsp/requests/prepare_rename.rb +4 -9
  71. data/lib/ruby_lsp/requests/prepare_type_hierarchy.rb +5 -15
  72. data/lib/ruby_lsp/requests/range_formatting.rb +5 -6
  73. data/lib/ruby_lsp/requests/references.rb +9 -53
  74. data/lib/ruby_lsp/requests/rename.rb +20 -46
  75. data/lib/ruby_lsp/requests/request.rb +8 -19
  76. data/lib/ruby_lsp/requests/selection_ranges.rb +6 -6
  77. data/lib/ruby_lsp/requests/semantic_highlighting.rb +16 -35
  78. data/lib/ruby_lsp/requests/show_syntax_tree.rb +7 -8
  79. data/lib/ruby_lsp/requests/signature_help.rb +8 -26
  80. data/lib/ruby_lsp/requests/support/annotation.rb +4 -10
  81. data/lib/ruby_lsp/requests/support/common.rb +15 -55
  82. data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +27 -35
  83. data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +11 -14
  84. data/lib/ruby_lsp/requests/support/rubocop_runner.rb +22 -34
  85. data/lib/ruby_lsp/requests/support/selection_range.rb +1 -3
  86. data/lib/ruby_lsp/requests/support/sorbet.rb +29 -38
  87. data/lib/ruby_lsp/requests/support/source_uri.rb +20 -32
  88. data/lib/ruby_lsp/requests/support/syntax_tree_formatter.rb +12 -19
  89. data/lib/ruby_lsp/requests/support/test_item.rb +16 -14
  90. data/lib/ruby_lsp/requests/type_hierarchy_supertypes.rb +5 -6
  91. data/lib/ruby_lsp/requests/workspace_symbol.rb +4 -4
  92. data/lib/ruby_lsp/response_builders/collection_response_builder.rb +5 -5
  93. data/lib/ruby_lsp/response_builders/document_symbol.rb +14 -19
  94. data/lib/ruby_lsp/response_builders/hover.rb +11 -14
  95. data/lib/ruby_lsp/response_builders/response_builder.rb +1 -1
  96. data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +60 -88
  97. data/lib/ruby_lsp/response_builders/signature_help.rb +5 -6
  98. data/lib/ruby_lsp/response_builders/test_collection.rb +43 -10
  99. data/lib/ruby_lsp/ruby_document.rb +24 -92
  100. data/lib/ruby_lsp/scope.rb +7 -11
  101. data/lib/ruby_lsp/scripts/compose_bundle.rb +6 -4
  102. data/lib/ruby_lsp/server.rb +182 -99
  103. data/lib/ruby_lsp/setup_bundler.rb +65 -60
  104. data/lib/ruby_lsp/static_docs.rb +11 -7
  105. data/lib/ruby_lsp/store.rb +29 -47
  106. data/lib/ruby_lsp/test_helper.rb +2 -12
  107. data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +191 -0
  108. data/lib/ruby_lsp/test_reporters/minitest_reporter.rb +105 -0
  109. data/lib/ruby_lsp/test_reporters/test_unit_reporter.rb +94 -0
  110. data/lib/ruby_lsp/type_inferrer.rb +13 -14
  111. data/lib/ruby_lsp/utils.rb +92 -83
  112. metadata +9 -3
@@ -25,10 +25,10 @@ module RubyIndexer
25
25
  tree = PrefixTree[String].new
26
26
  ["foo", "bar", "baz"].each { |item| tree.insert(item, item) }
27
27
 
28
- assert_equal(["foo", "bar", "baz"], tree.search(""))
29
- assert_equal(["bar", "baz"], tree.search("b"))
28
+ assert_equal(["baz", "bar", "foo"], tree.search(""))
29
+ assert_equal(["baz", "bar"], tree.search("b"))
30
30
  assert_equal(["foo"], tree.search("fo"))
31
- assert_equal(["bar", "baz"], tree.search("ba"))
31
+ assert_equal(["baz", "bar"], tree.search("ba"))
32
32
  assert_equal(["baz"], tree.search("baz"))
33
33
  assert_empty(tree.search("qux"))
34
34
  end
@@ -80,17 +80,17 @@ module RubyIndexer
80
80
 
81
81
  assert_equal(
82
82
  [
83
- "foo/bar/support/selection",
84
- "foo/bar/support/semantic",
85
- "foo/bar/support/syntax",
86
- "foo/bar/support/source",
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",
87
88
  "foo/bar/support/runner",
88
89
  "foo/bar/support/runner2",
89
- "foo/bar/support/rails",
90
- "foo/bar/support/diagnostic",
91
- "foo/bar/support/highlight",
92
- "foo/bar/support/prefix",
93
- "foo/bar/support/formatting",
90
+ "foo/bar/support/source",
91
+ "foo/bar/support/syntax",
92
+ "foo/bar/support/semantic",
93
+ "foo/bar/support/selection",
94
94
  ],
95
95
  tree.search("foo/bar/support"),
96
96
  )
@@ -99,7 +99,7 @@ module RubyIndexer
99
99
  def test_deletion
100
100
  tree = PrefixTree[String].new
101
101
  ["foo/bar", "foo/baz"].each { |item| tree.insert(item, item) }
102
- assert_equal(["foo/bar", "foo/baz"], tree.search("foo"))
102
+ assert_equal(["foo/baz", "foo/bar"], tree.search("foo"))
103
103
 
104
104
  tree.delete("foo/bar")
105
105
  assert_empty(tree.search("foo/bar"))
@@ -6,16 +6,16 @@ require_relative "test_case"
6
6
  module RubyIndexer
7
7
  class RBSIndexerTest < TestCase
8
8
  def test_index_core_classes
9
- entries = @index["Array"]
9
+ entries = @index["Array"] #: as !nil
10
10
  refute_nil(entries)
11
11
  # Array is a class but also an instance method on Kernel
12
12
  assert_equal(2, entries.length)
13
- entry = entries.find { |entry| entry.is_a?(RubyIndexer::Entry::Class) }
13
+ entry = entries.find { |entry| entry.is_a?(Entry::Class) } #: as Entry::Class
14
14
  assert_match(%r{/gems/rbs-.*/core/array.rbs}, entry.file_path)
15
15
  assert_equal("array.rbs", entry.file_name)
16
16
  assert_equal("Object", entry.parent_class)
17
17
  assert_equal(1, entry.mixin_operations.length)
18
- enumerable_include = entry.mixin_operations.first
18
+ enumerable_include = entry.mixin_operations.first #: as !nil
19
19
  assert_equal("Enumerable", enumerable_include.module_name)
20
20
 
21
21
  # Using fixed positions would be fragile, so let's just check some basics.
@@ -26,10 +26,10 @@ module RubyIndexer
26
26
  end
27
27
 
28
28
  def test_index_core_modules
29
- entries = @index["Kernel"]
29
+ entries = @index["Kernel"] #: as !nil
30
30
  refute_nil(entries)
31
31
  assert_equal(1, entries.length)
32
- entry = entries.first
32
+ entry = entries.first #: as Entry::Module
33
33
  assert_match(%r{/gems/rbs-.*/core/kernel.rbs}, entry.file_path)
34
34
  assert_equal("kernel.rbs", entry.file_name)
35
35
 
@@ -41,33 +41,26 @@ module RubyIndexer
41
41
  end
42
42
 
43
43
  def test_index_core_constants
44
- entries = @index["RUBY_VERSION"]
44
+ entries = @index["RUBY_VERSION"] #: as !nil
45
45
  refute_nil(entries)
46
46
  assert_equal(1, entries.length)
47
47
 
48
- # Complex::I is defined as `Complex::I = ...`
49
- entries = @index["Complex::I"]
48
+ entries = @index["Complex::I"] #: as !nil
50
49
  refute_nil(entries)
51
50
  assert_equal(1, entries.length)
52
51
 
53
- # Encoding::US_ASCII is defined as
54
- # ```
55
- # module Encoding
56
- # US_ASCII = ...
57
- # ...
58
- # ````
59
- entries = @index["Encoding::US_ASCII"]
52
+ entries = @index["Encoding::US_ASCII"] #: as !nil
60
53
  refute_nil(entries)
61
54
  assert_equal(1, entries.length)
62
55
  end
63
56
 
64
57
  def test_index_methods
65
- entries = @index["initialize"]
58
+ entries = @index["initialize"] #: as Array[Entry::Method]
66
59
  refute_nil(entries)
67
- entry = entries.find { |entry| entry.owner.name == "Array" }
60
+ entry = entries.find { |entry| entry.owner&.name == "Array" } #: as Entry::Method
68
61
  assert_match(%r{/gems/rbs-.*/core/array.rbs}, entry.file_path)
69
62
  assert_equal("array.rbs", entry.file_name)
70
- assert_equal(Entry::Visibility::PUBLIC, entry.visibility)
63
+ assert_equal(:public, entry.visibility)
71
64
 
72
65
  # Using fixed positions would be fragile, so let's just check some basics.
73
66
  assert_operator(entry.location.start_line, :>, 0)
@@ -77,11 +70,11 @@ module RubyIndexer
77
70
  end
78
71
 
79
72
  def test_index_global_declaration
80
- entries = @index["$DEBUG"]
73
+ entries = @index["$DEBUG"] #: as Array[Entry::GlobalVariable]
81
74
  refute_nil(entries)
82
75
  assert_equal(1, entries.length)
83
76
 
84
- entry = entries.first
77
+ entry = entries.first #: as Entry::GlobalVariable
85
78
 
86
79
  assert_instance_of(Entry::GlobalVariable, entry)
87
80
  assert_equal("$DEBUG", entry.name)
@@ -91,10 +84,10 @@ module RubyIndexer
91
84
  end
92
85
 
93
86
  def test_attaches_correct_owner_to_singleton_methods
94
- entries = @index["basename"]
87
+ entries = @index["basename"] #: as Array[Entry::Method]
95
88
  refute_nil(entries)
96
89
 
97
- owner = entries.first.owner
90
+ owner = entries.first&.owner #: as Entry::SingletonClass
98
91
  assert_instance_of(Entry::SingletonClass, owner)
99
92
  assert_equal("File::<Class:File>", owner.name)
100
93
  end
@@ -103,47 +96,47 @@ module RubyIndexer
103
96
  # NOTE: RBS does not store the name location for classes, modules or methods. This behavior is not exactly what
104
97
  # we would like, but for now we assign the same location to both
105
98
 
106
- entries = @index["Array"]
99
+ entries = @index["Array"] #: as Array[Entry::Class]
107
100
  refute_nil(entries)
108
- entry = entries.find { |entry| entry.is_a?(Entry::Class) }
101
+ entry = entries.find { |entry| entry.is_a?(Entry::Class) } #: as Entry::Class
109
102
 
110
103
  assert_same(entry.location, entry.name_location)
111
104
  end
112
105
 
113
106
  def test_rbs_method_with_required_positionals
114
- entries = @index["crypt"]
107
+ entries = @index["crypt"] #: as Array[Entry::Method]
115
108
  assert_equal(1, entries.length)
116
109
 
117
- entry = entries.first
110
+ entry = entries.first #: as Entry::Method
118
111
  signatures = entry.signatures
119
112
  assert_equal(1, signatures.length)
120
113
 
121
- first_signature = signatures.first
114
+ first_signature = signatures.first #: as Entry::Signature
122
115
 
123
116
  # (::string salt_str) -> ::String
124
117
 
125
118
  assert_equal(1, first_signature.parameters.length)
126
119
  assert_kind_of(Entry::RequiredParameter, first_signature.parameters[0])
127
- assert_equal(:salt_str, first_signature.parameters[0].name)
120
+ assert_equal(:salt_str, first_signature.parameters[0]&.name)
128
121
  end
129
122
 
130
123
  def test_rbs_method_with_unnamed_required_positionals
131
- entries = @index["try_convert"]
132
- entry = entries.find { |entry| entry.owner.name == "Array::<Class:Array>" }
124
+ entries = @index["try_convert"] #: as Array[Entry::Method]
125
+ entry = entries.find { |entry| entry.owner&.name == "Array::<Class:Array>" } #: as Entry::Method
133
126
 
134
- parameters = entry.signatures[0].parameters
127
+ parameters = entry.signatures[0]&.parameters #: as Array[Entry::Parameter]
135
128
 
136
129
  assert_equal([:arg0], parameters.map(&:name))
137
130
  assert_kind_of(Entry::RequiredParameter, parameters[0])
138
131
  end
139
132
 
140
133
  def test_rbs_method_with_optional_positionals
141
- entries = @index["polar"]
142
- entry = entries.find { |entry| entry.owner.name == "Complex::<Class:Complex>" }
134
+ entries = @index["polar"] #: as Array[Entry::Method]
135
+ entry = entries.find { |entry| entry.owner&.name == "Complex::<Class:Complex>" } #: as Entry::Method
143
136
 
144
137
  # def self.polar: (Numeric, ?Numeric) -> Complex
145
138
 
146
- parameters = entry.signatures[0].parameters
139
+ parameters = entry.signatures[0]&.parameters #: as Array[Entry::Parameter]
147
140
 
148
141
  assert_equal([:arg0, :arg1], parameters.map(&:name))
149
142
  assert_kind_of(Entry::RequiredParameter, parameters[0])
@@ -151,27 +144,27 @@ module RubyIndexer
151
144
  end
152
145
 
153
146
  def test_rbs_method_with_optional_parameter
154
- entries = @index["chomp"]
147
+ entries = @index["chomp"] #: as Array[Entry::Method]
155
148
  assert_equal(1, entries.length)
156
149
 
157
- entry = entries.first
150
+ entry = entries.first #: as Entry::Method
158
151
  signatures = entry.signatures
159
152
  assert_equal(1, signatures.length)
160
153
 
161
- first_signature = signatures.first
154
+ first_signature = signatures.first #: as Entry::Signature
162
155
 
163
156
  # (?::string? separator) -> ::String
164
157
 
165
158
  assert_equal(1, first_signature.parameters.length)
166
159
  assert_kind_of(Entry::OptionalParameter, first_signature.parameters[0])
167
- assert_equal(:separator, first_signature.parameters[0].name)
160
+ assert_equal(:separator, first_signature.parameters[0]&.name)
168
161
  end
169
162
 
170
163
  def test_rbs_method_with_required_and_optional_parameters
171
- entries = @index["gsub"]
164
+ entries = @index["gsub"] #: as Array[Entry::Method]
172
165
  assert_equal(1, entries.length)
173
166
 
174
- entry = entries.first
167
+ entry = entries.first #: as Entry::Method
175
168
 
176
169
  signatures = entry.signatures
177
170
  assert_equal(3, signatures.length)
@@ -180,37 +173,37 @@ module RubyIndexer
180
173
  # | (::Regexp | ::string pattern) -> ::Enumerator[::String, ::String]
181
174
  # | (::Regexp | ::string pattern) { (::String match) -> ::_ToS } -> ::String
182
175
 
183
- parameters = signatures[0].parameters
176
+ parameters = signatures[0]&.parameters #: as !nil
184
177
  assert_equal([:pattern, :replacement], parameters.map(&:name))
185
178
  assert_kind_of(Entry::RequiredParameter, parameters[0])
186
179
  assert_kind_of(Entry::RequiredParameter, parameters[1])
187
180
 
188
- parameters = signatures[1].parameters
181
+ parameters = signatures[1]&.parameters #: as !nil
189
182
  assert_equal([:pattern], parameters.map(&:name))
190
183
  assert_kind_of(Entry::RequiredParameter, parameters[0])
191
184
 
192
- parameters = signatures[2].parameters
185
+ parameters = signatures[2]&.parameters #: as !nil
193
186
  assert_equal([:pattern, :"<anonymous block>"], parameters.map(&:name))
194
187
  assert_kind_of(Entry::RequiredParameter, parameters[0])
195
188
  assert_kind_of(Entry::BlockParameter, parameters[1])
196
189
  end
197
190
 
198
191
  def test_rbs_anonymous_block_parameter
199
- entries = @index["open"]
200
- entry = entries.find { |entry| entry.owner.name == "File::<Class:File>" }
192
+ entries = @index["open"] #: as Array[Entry::Method]
193
+ entry = entries.find { |entry| entry.owner&.name == "File::<Class:File>" } #: as Entry::Method
201
194
 
202
195
  assert_equal(2, entry.signatures.length)
203
196
 
204
197
  # (::String name, ?::String mode, ?::Integer perm) -> ::IO?
205
198
  # | [T] (::String name, ?::String mode, ?::Integer perm) { (::IO) -> T } -> T
206
199
 
207
- parameters = entry.signatures[0].parameters
200
+ parameters = entry.signatures[0]&.parameters #: as !nil
208
201
  assert_equal([:file_name, :mode, :perm], parameters.map(&:name))
209
202
  assert_kind_of(Entry::RequiredParameter, parameters[0])
210
203
  assert_kind_of(Entry::OptionalParameter, parameters[1])
211
204
  assert_kind_of(Entry::OptionalParameter, parameters[2])
212
205
 
213
- parameters = entry.signatures[1].parameters
206
+ parameters = entry.signatures[1]&.parameters #: as !nil
214
207
  assert_equal([:file_name, :mode, :perm, :"<anonymous block>"], parameters.map(&:name))
215
208
  assert_kind_of(Entry::RequiredParameter, parameters[0])
216
209
  assert_kind_of(Entry::OptionalParameter, parameters[1])
@@ -219,10 +212,10 @@ module RubyIndexer
219
212
  end
220
213
 
221
214
  def test_rbs_method_with_rest_positionals
222
- entries = @index["count"]
223
- entry = entries.find { |entry| entry.owner.name == "String" }
215
+ entries = @index["count"] #: as Array[Entry::Method]
216
+ entry = entries.find { |entry| entry.owner&.name == "String" } #: as Entry::Method
224
217
 
225
- parameters = entry.signatures.first.parameters
218
+ parameters = entry.signatures.first&.parameters #: as !nil
226
219
  assert_equal(1, entry.signatures.length)
227
220
 
228
221
  # (::String::selector selector_0, *::String::selector more_selectors) -> ::Integer
@@ -233,8 +226,8 @@ module RubyIndexer
233
226
  end
234
227
 
235
228
  def test_rbs_method_with_trailing_positionals
236
- entries = @index["select"] # https://ruby-doc.org/3.3.3/IO.html#method-c-select
237
- entry = entries.find { |entry| entry.owner.name == "IO::<Class:IO>" }
229
+ entries = @index["select"] #: as Array[Entry::Method]
230
+ entry = entries.find { |entry| entry.owner&.name == "IO::<Class:IO>" } #: as !nil
238
231
 
239
232
  signatures = entry.signatures
240
233
  assert_equal(2, signatures.length)
@@ -242,13 +235,13 @@ module RubyIndexer
242
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] ] # rubocop:disable Layout/LineLength
243
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] ]? # rubocop:disable Layout/LineLength
244
237
 
245
- parameters = signatures[0].parameters
238
+ parameters = signatures[0]&.parameters #: as !nil
246
239
  assert_equal([:read_array, :write_array, :error_array], parameters.map(&:name))
247
240
  assert_kind_of(Entry::RequiredParameter, parameters[0])
248
241
  assert_kind_of(Entry::OptionalParameter, parameters[1])
249
242
  assert_kind_of(Entry::OptionalParameter, parameters[2])
250
243
 
251
- parameters = signatures[1].parameters
244
+ parameters = signatures[1]&.parameters #: as !nil
252
245
  assert_equal([:read_array, :write_array, :error_array, :timeout], parameters.map(&:name))
253
246
  assert_kind_of(Entry::RequiredParameter, parameters[0])
254
247
  assert_kind_of(Entry::OptionalParameter, parameters[1])
@@ -257,8 +250,8 @@ module RubyIndexer
257
250
  end
258
251
 
259
252
  def test_rbs_method_with_optional_keywords
260
- entries = @index["step"]
261
- entry = entries.find { |entry| entry.owner.name == "Numeric" }
253
+ entries = @index["step"] #: as Array[Entry::Method]
254
+ entry = entries.find { |entry| entry.owner&.name == "Numeric" } #: as !nil
262
255
 
263
256
  signatures = entry.signatures
264
257
  assert_equal(4, signatures.length)
@@ -268,24 +261,24 @@ module RubyIndexer
268
261
  # | (?by: ::Numeric, ?to: ::Numeric) { (::Numeric) -> void } -> self
269
262
  # | (?by: ::Numeric, ?to: ::Numeric) -> ::Enumerator[::Numeric, self]
270
263
 
271
- parameters = signatures[0].parameters
264
+ parameters = signatures[0]&.parameters #: as !nil
272
265
  assert_equal([:limit, :step, :"<anonymous block>"], parameters.map(&:name))
273
266
  assert_kind_of(Entry::OptionalParameter, parameters[0])
274
267
  assert_kind_of(Entry::OptionalParameter, parameters[1])
275
268
  assert_kind_of(Entry::BlockParameter, parameters[2])
276
269
 
277
- parameters = signatures[1].parameters
270
+ parameters = signatures[1]&.parameters #: as !nil
278
271
  assert_equal([:limit, :step], parameters.map(&:name))
279
272
  assert_kind_of(Entry::OptionalParameter, parameters[0])
280
273
  assert_kind_of(Entry::OptionalParameter, parameters[1])
281
274
 
282
- parameters = signatures[2].parameters
275
+ parameters = signatures[2]&.parameters #: as !nil
283
276
  assert_equal([:by, :to, :"<anonymous block>"], parameters.map(&:name))
284
277
  assert_kind_of(Entry::OptionalKeywordParameter, parameters[0])
285
278
  assert_kind_of(Entry::OptionalKeywordParameter, parameters[1])
286
279
  assert_kind_of(Entry::BlockParameter, parameters[2])
287
280
 
288
- parameters = signatures[3].parameters
281
+ parameters = signatures[3]&.parameters #: as !nil
289
282
  assert_equal([:by, :to], parameters.map(&:name))
290
283
  assert_kind_of(Entry::OptionalKeywordParameter, parameters[0])
291
284
  assert_kind_of(Entry::OptionalKeywordParameter, parameters[1])
@@ -308,14 +301,14 @@ module RubyIndexer
308
301
  end
309
302
 
310
303
  def test_rbs_method_with_rest_keywords
311
- entries = @index["method_missing"]
312
- entry = entries.find { |entry| entry.owner.name == "BasicObject" }
304
+ entries = @index["method_missing"] #: as Array[Entry::Method]
305
+ entry = entries.find { |entry| entry.owner&.name == "BasicObject" } #: as !nil
313
306
  signatures = entry.signatures
314
307
  assert_equal(1, signatures.length)
315
308
 
316
309
  # (Symbol, *untyped, **untyped) ?{ (*untyped, **untyped) -> untyped } -> untyped
317
310
 
318
- parameters = signatures[0].parameters
311
+ parameters = signatures[0]&.parameters #: as !nil
319
312
  assert_equal([:arg0, :"<anonymous splat>", :"<anonymous keyword splat>"], parameters.map(&:name))
320
313
  assert_kind_of(Entry::RequiredParameter, parameters[0])
321
314
  assert_kind_of(Entry::RestParameter, parameters[1])
@@ -348,24 +341,24 @@ module RubyIndexer
348
341
  def test_signature_alias
349
342
  # In RBS, an alias means that two methods have the same signature.
350
343
  # It does not mean the same thing as a Ruby alias.
351
- any_entries = @index["any?"]
344
+ any_entries = @index["any?"] #: as Array[Entry::UnresolvedMethodAlias]
352
345
 
353
- assert_equal(["Array", "Enumerable", "Hash"], any_entries.map { _1.owner.name })
346
+ assert_equal(["Array", "Enumerable", "Hash"], any_entries.map { _1.owner&.name })
354
347
 
355
- entry = any_entries.find { |entry| entry.owner.name == "Array" }
348
+ entry = any_entries.find { |entry| entry.owner&.name == "Array" } #: as !nil
356
349
 
357
350
  assert_kind_of(RubyIndexer::Entry::UnresolvedMethodAlias, entry)
358
351
  assert_equal("any?", entry.name)
359
352
  assert_equal("all?", entry.old_name)
360
- assert_equal("Array", entry.owner.name)
361
- assert(entry.file_path.end_with?("core/array.rbs"))
362
- assert_includes(entry.comments, "Returns `true` if any element of `self` meets a given criterion.")
353
+ assert_equal("Array", entry.owner&.name)
354
+ assert(entry.file_path&.end_with?("core/array.rbs"))
355
+ refute_empty(entry.comments)
363
356
  end
364
357
 
365
358
  def test_indexing_untyped_functions
366
- entries = @index.resolve_method("call", "Method")
359
+ entries = @index.resolve_method("call", "Method") #: as Array[Entry::Method]
367
360
 
368
- parameters = entries.first.signatures.first.parameters
361
+ parameters = entries.first&.signatures&.first&.parameters #: as !nil
369
362
  assert_equal(1, parameters.length)
370
363
  assert_instance_of(Entry::ForwardingParameter, parameters.first)
371
364
  end
@@ -379,8 +372,10 @@ module RubyIndexer
379
372
  indexer = RubyIndexer::RBSIndexer.new(index)
380
373
  pathname = Pathname.new("/file.rbs")
381
374
  indexer.process_signature(pathname, declarations)
382
- entry = T.must(index[method_name]).first
383
- T.cast(entry, Entry::Method).signatures
375
+ entry = index[method_name] #: as !nil
376
+ .first #: as Entry::Method
377
+
378
+ entry.signatures
384
379
  end
385
380
  end
386
381
  end
@@ -11,6 +11,13 @@ module RubyIndexer
11
11
  @default_indexed_entries = @index.instance_variable_get(:@entries).dup
12
12
  end
13
13
 
14
+ def teardown
15
+ entries = @index.instance_variable_get(:@entries).values.flatten
16
+ entries.each do |entry|
17
+ assert_includes([:public, :private, :protected], entry.visibility)
18
+ end
19
+ end
20
+
14
21
  private
15
22
 
16
23
  def index(source, uri: URI::Generic.from_path(path: "/fake/path/foo.rb"))
@@ -18,11 +25,11 @@ module RubyIndexer
18
25
  end
19
26
 
20
27
  def assert_entry(expected_name, type, expected_location, visibility: nil)
21
- entries = @index[expected_name]
28
+ entries = @index[expected_name] #: as !nil
22
29
  refute_nil(entries, "Expected #{expected_name} to be indexed")
23
30
  refute_empty(entries, "Expected #{expected_name} to be indexed")
24
31
 
25
- entry = entries.first
32
+ entry = entries.first #: as !nil
26
33
  assert_instance_of(type, entry, "Expected #{expected_name} to be a #{type}")
27
34
 
28
35
  location = entry.location
@@ -31,7 +38,6 @@ module RubyIndexer
31
38
  ":#{location.end_line - 1}-#{location.end_column}"
32
39
 
33
40
  assert_equal(expected_location, location_string)
34
-
35
41
  assert_equal(visibility, entry.visibility) if visibility
36
42
  end
37
43
 
@@ -12,12 +12,12 @@ module RubyIndexer
12
12
 
13
13
  def test_from_path_on_windows
14
14
  uri = URI::Generic.from_path(path: "C:/some/windows/path/to/file.rb")
15
- assert_equal("/C:/some/windows/path/to/file.rb", uri.path)
15
+ assert_equal("/C%3A/some/windows/path/to/file.rb", uri.path)
16
16
  end
17
17
 
18
18
  def test_from_path_on_windows_with_lowercase_drive
19
19
  uri = URI::Generic.from_path(path: "c:/some/windows/path/to/file.rb")
20
- assert_equal("/c:/some/windows/path/to/file.rb", uri.path)
20
+ assert_equal("/c%3A/some/windows/path/to/file.rb", uri.path)
21
21
  end
22
22
 
23
23
  def test_to_standardized_path_on_unix
@@ -68,5 +68,18 @@ module RubyIndexer
68
68
  uri.add_require_path_from_load_entry("/some/unix/path")
69
69
  assert_equal("to/file", uri.require_path)
70
70
  end
71
+
72
+ def test_from_path_escapes_colon_characters
73
+ uri = URI::Generic.from_path(path: "c:/some/windows/path with/spaces/file.rb")
74
+ assert_equal("c:/some/windows/path with/spaces/file.rb", uri.to_standardized_path)
75
+ assert_equal("file:///c%3A/some/windows/path%20with/spaces/file.rb", uri.to_s)
76
+ end
77
+
78
+ def test_from_path_with_unicode_characters
79
+ path = "/path/with/unicode/文件.rb"
80
+ uri = URI::Generic.from_path(path: path)
81
+ assert_equal(path, uri.to_standardized_path)
82
+ assert_equal("file:///path/with/unicode/%E6%96%87%E4%BB%B6.rb", uri.to_s)
83
+ end
71
84
  end
72
85
  end