ruby-lsp 0.23.15 → 0.26.9

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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/exe/ruby-lsp +17 -14
  4. data/exe/ruby-lsp-check +0 -4
  5. data/exe/ruby-lsp-launcher +41 -14
  6. data/exe/ruby-lsp-test-exec +6 -0
  7. data/lib/rubocop/cop/ruby_lsp/use_language_server_aliases.rb +0 -1
  8. data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +0 -1
  9. data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +4 -3
  10. data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +42 -20
  11. data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +1 -7
  12. data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +49 -62
  13. data/lib/ruby_indexer/lib/ruby_indexer/index.rb +84 -74
  14. data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +6 -9
  15. data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +9 -14
  16. data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +12 -8
  17. data/lib/ruby_indexer/lib/ruby_indexer/visibility_scope.rb +4 -4
  18. data/lib/ruby_lsp/addon.rb +44 -15
  19. data/lib/ruby_lsp/base_server.rb +56 -37
  20. data/lib/ruby_lsp/client_capabilities.rb +6 -1
  21. data/lib/ruby_lsp/document.rb +174 -62
  22. data/lib/ruby_lsp/erb_document.rb +10 -8
  23. data/lib/ruby_lsp/global_state.rb +86 -33
  24. data/lib/ruby_lsp/internal.rb +6 -3
  25. data/lib/ruby_lsp/listeners/completion.rb +22 -11
  26. data/lib/ruby_lsp/listeners/definition.rb +41 -21
  27. data/lib/ruby_lsp/listeners/document_highlight.rb +26 -1
  28. data/lib/ruby_lsp/listeners/document_link.rb +64 -28
  29. data/lib/ruby_lsp/listeners/hover.rb +27 -16
  30. data/lib/ruby_lsp/listeners/inlay_hints.rb +5 -3
  31. data/lib/ruby_lsp/listeners/semantic_highlighting.rb +2 -2
  32. data/lib/ruby_lsp/listeners/signature_help.rb +2 -2
  33. data/lib/ruby_lsp/listeners/spec_style.rb +155 -79
  34. data/lib/ruby_lsp/listeners/test_discovery.rb +39 -21
  35. data/lib/ruby_lsp/listeners/test_style.rb +75 -35
  36. data/lib/ruby_lsp/rbs_document.rb +3 -6
  37. data/lib/ruby_lsp/requests/code_action_resolve.rb +83 -58
  38. data/lib/ruby_lsp/requests/code_actions.rb +20 -5
  39. data/lib/ruby_lsp/requests/code_lens.rb +27 -6
  40. data/lib/ruby_lsp/requests/completion.rb +3 -3
  41. data/lib/ruby_lsp/requests/completion_resolve.rb +8 -6
  42. data/lib/ruby_lsp/requests/definition.rb +4 -7
  43. data/lib/ruby_lsp/requests/discover_tests.rb +2 -2
  44. data/lib/ruby_lsp/requests/document_highlight.rb +2 -2
  45. data/lib/ruby_lsp/requests/document_link.rb +1 -1
  46. data/lib/ruby_lsp/requests/folding_ranges.rb +1 -1
  47. data/lib/ruby_lsp/requests/go_to_relevant_file.rb +64 -12
  48. data/lib/ruby_lsp/requests/hover.rb +3 -6
  49. data/lib/ruby_lsp/requests/inlay_hints.rb +4 -4
  50. data/lib/ruby_lsp/requests/on_type_formatting.rb +1 -1
  51. data/lib/ruby_lsp/requests/prepare_rename.rb +1 -1
  52. data/lib/ruby_lsp/requests/references.rb +10 -21
  53. data/lib/ruby_lsp/requests/rename.rb +9 -10
  54. data/lib/ruby_lsp/requests/request.rb +8 -8
  55. data/lib/ruby_lsp/requests/selection_ranges.rb +2 -2
  56. data/lib/ruby_lsp/requests/semantic_highlighting.rb +1 -1
  57. data/lib/ruby_lsp/requests/show_syntax_tree.rb +2 -2
  58. data/lib/ruby_lsp/requests/signature_help.rb +2 -2
  59. data/lib/ruby_lsp/requests/support/annotation.rb +1 -1
  60. data/lib/ruby_lsp/requests/support/common.rb +9 -12
  61. data/lib/ruby_lsp/requests/support/formatter.rb +16 -15
  62. data/lib/ruby_lsp/requests/support/package_url.rb +414 -0
  63. data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +7 -1
  64. data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +2 -2
  65. data/lib/ruby_lsp/requests/support/rubocop_runner.rb +13 -3
  66. data/lib/ruby_lsp/requests/support/source_uri.rb +7 -4
  67. data/lib/ruby_lsp/requests/support/test_item.rb +7 -1
  68. data/lib/ruby_lsp/requests/workspace_symbol.rb +20 -12
  69. data/lib/ruby_lsp/response_builders/collection_response_builder.rb +1 -4
  70. data/lib/ruby_lsp/response_builders/document_symbol.rb +2 -3
  71. data/lib/ruby_lsp/response_builders/hover.rb +1 -4
  72. data/lib/ruby_lsp/response_builders/response_builder.rb +6 -7
  73. data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +4 -5
  74. data/lib/ruby_lsp/response_builders/signature_help.rb +1 -2
  75. data/lib/ruby_lsp/response_builders/test_collection.rb +29 -3
  76. data/lib/ruby_lsp/ruby_document.rb +14 -42
  77. data/lib/ruby_lsp/scripts/compose_bundle.rb +3 -3
  78. data/lib/ruby_lsp/scripts/compose_bundle_windows.rb +3 -1
  79. data/lib/ruby_lsp/server.rb +173 -130
  80. data/lib/ruby_lsp/setup_bundler.rb +114 -47
  81. data/lib/ruby_lsp/static_docs.rb +1 -0
  82. data/lib/ruby_lsp/store.rb +6 -16
  83. data/lib/ruby_lsp/test_helper.rb +1 -4
  84. data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +121 -17
  85. data/lib/ruby_lsp/test_reporters/minitest_reporter.rb +65 -25
  86. data/lib/ruby_lsp/test_reporters/test_unit_reporter.rb +16 -18
  87. data/lib/ruby_lsp/utils.rb +102 -13
  88. data/static_docs/break.md +103 -0
  89. metadata +8 -33
  90. data/lib/ruby_indexer/test/class_variables_test.rb +0 -140
  91. data/lib/ruby_indexer/test/classes_and_modules_test.rb +0 -770
  92. data/lib/ruby_indexer/test/configuration_test.rb +0 -280
  93. data/lib/ruby_indexer/test/constant_test.rb +0 -402
  94. data/lib/ruby_indexer/test/enhancements_test.rb +0 -325
  95. data/lib/ruby_indexer/test/global_variable_test.rb +0 -49
  96. data/lib/ruby_indexer/test/index_test.rb +0 -2190
  97. data/lib/ruby_indexer/test/instance_variables_test.rb +0 -240
  98. data/lib/ruby_indexer/test/method_test.rb +0 -973
  99. data/lib/ruby_indexer/test/prefix_tree_test.rb +0 -150
  100. data/lib/ruby_indexer/test/rbs_indexer_test.rb +0 -380
  101. data/lib/ruby_indexer/test/reference_finder_test.rb +0 -330
  102. data/lib/ruby_indexer/test/test_case.rb +0 -51
  103. data/lib/ruby_indexer/test/uri_test.rb +0 -85
  104. data/lib/ruby_lsp/load_sorbet.rb +0 -62
@@ -1,280 +0,0 @@
1
- # typed: true
2
- # frozen_string_literal: true
3
-
4
- require "test_helper"
5
-
6
- module RubyIndexer
7
- class ConfigurationTest < Minitest::Test
8
- def setup
9
- @config = Configuration.new
10
- @workspace_path = File.expand_path(File.join("..", "..", ".."), __dir__)
11
- @config.workspace_path = @workspace_path
12
- end
13
-
14
- def test_load_configuration_executes_configure_block
15
- @config.apply_config({ "excluded_patterns" => ["**/fixtures/**/*"] })
16
- uris = @config.indexable_uris
17
-
18
- bundle_path = Bundler.bundle_path.join("gems")
19
-
20
- assert(uris.none? { |uri| uri.full_path.include?("test/fixtures") })
21
- assert(uris.none? { |uri| uri.full_path.include?(bundle_path.join("minitest-reporters").to_s) })
22
- assert(uris.none? { |uri| uri.full_path.include?(bundle_path.join("ansi").to_s) })
23
- assert(uris.any? { |uri| uri.full_path.include?(bundle_path.join("sorbet-runtime").to_s) })
24
- assert(uris.none? { |uri| uri.full_path == __FILE__ })
25
- end
26
-
27
- def test_indexable_uris_have_expanded_full_paths
28
- @config.apply_config({ "included_patterns" => ["**/*.rb"] })
29
- uris = @config.indexable_uris
30
-
31
- # All paths should be expanded
32
- assert(uris.all? { |uri| File.absolute_path?(uri.full_path) })
33
- end
34
-
35
- def test_indexable_uris_only_includes_gem_require_paths
36
- uris = @config.indexable_uris
37
-
38
- Bundler.locked_gems.specs.each do |lazy_spec|
39
- next if lazy_spec.name == "ruby-lsp"
40
-
41
- spec = Gem::Specification.find_by_name(lazy_spec.name)
42
-
43
- test_uris = uris.select do |uri|
44
- File.fnmatch?(File.join(spec.full_gem_path, "test/**/*"), uri.full_path, File::Constants::FNM_PATHNAME)
45
- end
46
- assert_empty(test_uris)
47
- rescue Gem::MissingSpecError
48
- # Transitive dependencies might be missing when running tests on Windows
49
- end
50
- end
51
-
52
- def test_indexable_uris_does_not_include_default_gem_path_when_in_bundle
53
- uris = @config.indexable_uris
54
- assert(uris.none? { |uri| uri.full_path.start_with?("#{RbConfig::CONFIG["rubylibdir"]}/psych") })
55
- end
56
-
57
- def test_indexable_uris_includes_default_gems
58
- paths = @config.indexable_uris.map(&:full_path)
59
-
60
- assert_includes(paths, "#{RbConfig::CONFIG["rubylibdir"]}/pathname.rb")
61
- assert_includes(paths, "#{RbConfig::CONFIG["rubylibdir"]}/ipaddr.rb")
62
- assert_includes(paths, "#{RbConfig::CONFIG["rubylibdir"]}/erb.rb")
63
- end
64
-
65
- def test_indexable_uris_includes_project_files
66
- paths = @config.indexable_uris.map(&:full_path)
67
-
68
- Dir.glob("#{Dir.pwd}/lib/**/*.rb").each do |path|
69
- next if path.end_with?("_test.rb")
70
-
71
- assert_includes(paths, path)
72
- end
73
- end
74
-
75
- def test_indexable_uris_avoids_duplicates_if_bundle_path_is_inside_project
76
- Bundler.settings.temporary(path: "vendor/bundle") do
77
- config = Configuration.new
78
-
79
- assert_includes(config.instance_variable_get(:@excluded_patterns), "vendor/bundle/**/*.rb")
80
- end
81
- end
82
-
83
- def test_indexable_uris_does_not_include_gems_own_installed_files
84
- uris = @config.indexable_uris
85
- uris_inside_bundled_lsp = uris.select do |uri|
86
- uri.full_path.start_with?(Bundler.bundle_path.join("gems", "ruby-lsp").to_s)
87
- end
88
-
89
- assert_empty(
90
- uris_inside_bundled_lsp,
91
- "Indexable URIs should not include files from the gem currently being worked on. " \
92
- "Included: #{uris_inside_bundled_lsp.map(&:full_path)}",
93
- )
94
- end
95
-
96
- def test_indexable_uris_does_not_include_non_ruby_files_inside_rubylibdir
97
- path = Pathname.new(RbConfig::CONFIG["rubylibdir"]).join("extra_file.txt").to_s
98
- FileUtils.touch(path)
99
-
100
- begin
101
- uris = @config.indexable_uris
102
- assert(uris.none? { |uri| uri.full_path == path })
103
- ensure
104
- FileUtils.rm(path)
105
- end
106
- end
107
-
108
- def test_paths_are_unique
109
- uris = @config.indexable_uris
110
- assert_equal(uris.uniq.length, uris.length)
111
- end
112
-
113
- def test_configuration_raises_for_unknown_keys
114
- assert_raises(ArgumentError) do
115
- @config.apply_config({ "unknown_config" => 123 })
116
- end
117
- end
118
-
119
- def test_magic_comments_regex
120
- regex = @config.magic_comment_regex
121
-
122
- [
123
- "# frozen_string_literal:",
124
- "# typed:",
125
- "# compiled:",
126
- "# encoding:",
127
- "# shareable_constant_value:",
128
- "# warn_indent:",
129
- "# rubocop:",
130
- "# nodoc:",
131
- "# doc:",
132
- "# coding:",
133
- "# warn_past_scope:",
134
- ].each do |comment|
135
- assert_match(regex, comment)
136
- end
137
- end
138
-
139
- def test_indexable_uris_respect_given_workspace_path
140
- Dir.mktmpdir do |dir|
141
- FileUtils.mkdir(File.join(dir, "ignore"))
142
- FileUtils.touch(File.join(dir, "ignore", "file0.rb"))
143
- FileUtils.touch(File.join(dir, "file1.rb"))
144
- FileUtils.touch(File.join(dir, "file2.rb"))
145
-
146
- @config.apply_config({ "excluded_patterns" => ["ignore/**/*.rb"] })
147
- @config.workspace_path = dir
148
-
149
- uris = @config.indexable_uris
150
- assert(uris.none? { |uri| uri.full_path.start_with?(File.join(dir, "ignore")) })
151
-
152
- # The regular default gem path is ~/.rubies/3.4.1/lib/ruby/3.4.0
153
- # The alternative default gem path is ~/.rubies/3.4.1/lib/ruby/gems/3.4.0
154
- # Here part_1 contains ~/.rubies/3.4.1/lib/ruby/ and part_2 contains 3.4.0, so that we can turn it into the
155
- # alternative path
156
- part_1, part_2 = Pathname.new(RbConfig::CONFIG["rubylibdir"]).split
157
- other_default_gem_dir = part_1.join("gems").join(part_2).to_s
158
-
159
- # After switching the workspace path, all indexable URIs will be found in one of these places:
160
- # - The new workspace path
161
- # - The Ruby LSP's own code (because Bundler is requiring the dependency from source)
162
- # - Bundled gems
163
- # - Default gems
164
- # - Other default gem directory
165
- assert(
166
- uris.all? do |u|
167
- u.full_path.start_with?(dir) ||
168
- u.full_path.start_with?(File.join(Dir.pwd, "lib")) ||
169
- u.full_path.start_with?(Bundler.bundle_path.to_s) ||
170
- u.full_path.start_with?(RbConfig::CONFIG["rubylibdir"]) ||
171
- u.full_path.start_with?(other_default_gem_dir)
172
- end,
173
- )
174
- end
175
- end
176
-
177
- def test_includes_top_level_files
178
- Dir.mktmpdir do |dir|
179
- FileUtils.touch(File.join(dir, "find_me.rb"))
180
- @config.workspace_path = dir
181
-
182
- uris = @config.indexable_uris
183
- assert(uris.find { |u| File.basename(u.full_path) == "find_me.rb" })
184
- end
185
- end
186
-
187
- def test_transitive_dependencies_for_non_dev_gems_are_not_excluded
188
- Dir.mktmpdir do |dir|
189
- Dir.chdir(dir) do
190
- # Both IRB and debug depend on reline. Since IRB is in the default group, reline should not be excluded
191
- File.write(File.join(dir, "Gemfile"), <<~RUBY)
192
- source "https://rubygems.org"
193
- gem "irb"
194
- gem "ruby-lsp", path: "#{Bundler.root}"
195
-
196
- group :development do
197
- gem "debug"
198
- end
199
- RUBY
200
-
201
- Bundler.with_unbundled_env do
202
- capture_subprocess_io do
203
- system("bundle install")
204
- end
205
-
206
- stdout, _stderr = capture_subprocess_io do
207
- script = [
208
- "require \"ruby_lsp/internal\"",
209
- "print RubyIndexer::Configuration.new.instance_variable_get(:@excluded_gems).join(\",\")",
210
- ].join(";")
211
- system("bundle exec ruby -e '#{script}'")
212
- end
213
-
214
- excluded_gems = stdout.split(",")
215
- assert_includes(excluded_gems, "debug")
216
- refute_includes(excluded_gems, "reline")
217
- refute_includes(excluded_gems, "irb")
218
- end
219
- end
220
- end
221
- end
222
-
223
- def test_does_not_fail_if_there_are_missing_specs_due_to_platform_constraints
224
- Dir.mktmpdir do |dir|
225
- Dir.chdir(dir) do
226
- File.write(File.join(dir, "Gemfile"), <<~RUBY)
227
- source "https://rubygems.org"
228
- gem "ruby-lsp", path: "#{Bundler.root}"
229
-
230
- platforms :windows do
231
- gem "tzinfo"
232
- gem "tzinfo-data"
233
- end
234
- RUBY
235
-
236
- Bundler.with_unbundled_env do
237
- capture_subprocess_io { system("bundle install") }
238
-
239
- _stdout, stderr = capture_subprocess_io do
240
- script = [
241
- "require \"ruby_lsp/internal\"",
242
- "RubyIndexer::Configuration.new.indexable_uris",
243
- ].join(";")
244
-
245
- system("bundle exec ruby -e '#{script}'")
246
- end
247
-
248
- assert_empty(stderr)
249
- end
250
- end
251
- end
252
- end
253
-
254
- def test_indexables_include_non_test_files_in_test_directories
255
- # In order to linearize test parent classes and accurately detect the framework being used, then intermediate
256
- # parent classes _must_ also be indexed. Otherwise, we have no way of linearizing the rest of the ancestors to
257
- # determine what the test class ultimately inherits from.
258
- #
259
- # Therefore, we need to ensure that test files are excluded, but non test files inside test directories have to be
260
- # indexed
261
- FileUtils.touch("test/test_case.rb")
262
-
263
- uris = @config.indexable_uris
264
- project_paths = uris.filter_map do |uri|
265
- path = uri.full_path
266
- next if path.start_with?(Bundler.bundle_path.to_s) || path.start_with?(RbConfig::CONFIG["rubylibdir"])
267
-
268
- Pathname.new(path).relative_path_from(Dir.pwd).to_s
269
- end
270
-
271
- begin
272
- assert_includes(project_paths, "test/requests/support/expectations_test_runner.rb")
273
- assert_includes(project_paths, "test/test_helper.rb")
274
- assert_includes(project_paths, "test/test_case.rb")
275
- ensure
276
- FileUtils.rm("test/test_case.rb")
277
- end
278
- end
279
- end
280
- end
@@ -1,402 +0,0 @@
1
- # typed: true
2
- # frozen_string_literal: true
3
-
4
- require_relative "test_case"
5
-
6
- module RubyIndexer
7
- class ConstantTest < TestCase
8
- def test_constant_writes
9
- index(<<~RUBY)
10
- FOO = 1
11
-
12
- class ::Bar
13
- FOO = 2
14
- end
15
-
16
- BAR = 3 if condition
17
- RUBY
18
-
19
- assert_entry("FOO", Entry::Constant, "/fake/path/foo.rb:0-0:0-7")
20
- assert_entry("Bar::FOO", Entry::Constant, "/fake/path/foo.rb:3-2:3-9")
21
- assert_entry("BAR", Entry::Constant, "/fake/path/foo.rb:6-0:6-7")
22
- end
23
-
24
- def test_constant_with_multibyte_characters
25
- index(<<~RUBY)
26
- CONST_💎 = "Ruby"
27
- RUBY
28
-
29
- assert_entry("CONST_💎", Entry::Constant, "/fake/path/foo.rb:0-0:0-16")
30
- end
31
-
32
- def test_constant_or_writes
33
- index(<<~RUBY)
34
- FOO ||= 1
35
-
36
- class ::Bar
37
- FOO ||= 2
38
- end
39
- RUBY
40
-
41
- assert_entry("FOO", Entry::Constant, "/fake/path/foo.rb:0-0:0-9")
42
- assert_entry("Bar::FOO", Entry::Constant, "/fake/path/foo.rb:3-2:3-11")
43
- end
44
-
45
- def test_constant_path_writes
46
- index(<<~RUBY)
47
- class A
48
- FOO = 1
49
- ::BAR = 1
50
-
51
- module B
52
- FOO = 1
53
- end
54
- end
55
-
56
- A::BAZ = 1
57
- RUBY
58
-
59
- assert_entry("A::FOO", Entry::Constant, "/fake/path/foo.rb:1-2:1-9")
60
- assert_entry("BAR", Entry::Constant, "/fake/path/foo.rb:2-2:2-11")
61
- assert_entry("A::B::FOO", Entry::Constant, "/fake/path/foo.rb:5-4:5-11")
62
- assert_entry("A::BAZ", Entry::Constant, "/fake/path/foo.rb:9-0:9-10")
63
- end
64
-
65
- def test_constant_path_or_writes
66
- index(<<~RUBY)
67
- class A
68
- FOO ||= 1
69
- ::BAR ||= 1
70
- end
71
-
72
- A::BAZ ||= 1
73
- RUBY
74
-
75
- assert_entry("A::FOO", Entry::Constant, "/fake/path/foo.rb:1-2:1-11")
76
- assert_entry("BAR", Entry::Constant, "/fake/path/foo.rb:2-2:2-13")
77
- assert_entry("A::BAZ", Entry::Constant, "/fake/path/foo.rb:5-0:5-12")
78
- end
79
-
80
- def test_comments_for_constants
81
- index(<<~RUBY)
82
- # FOO comment
83
- FOO = 1
84
-
85
- class A
86
- # A::FOO comment
87
- FOO = 1
88
-
89
- # ::BAR comment
90
- ::BAR = 1
91
- end
92
-
93
- # A::BAZ comment
94
- A::BAZ = 1
95
- RUBY
96
-
97
- foo = @index["FOO"]&.first #: as !nil
98
- assert_equal("FOO comment", foo.comments)
99
-
100
- a_foo = @index["A::FOO"]&.first #: as !nil
101
- assert_equal("A::FOO comment", a_foo.comments)
102
-
103
- bar = @index["BAR"]&.first #: as !nil
104
- assert_equal("::BAR comment", bar.comments)
105
-
106
- a_baz = @index["A::BAZ"]&.first #: as !nil
107
- assert_equal("A::BAZ comment", a_baz.comments)
108
- end
109
-
110
- def test_variable_path_constants_are_ignored
111
- index(<<~RUBY)
112
- var::FOO = 1
113
- self.class::FOO = 1
114
- RUBY
115
-
116
- assert_no_indexed_entries
117
- end
118
-
119
- def test_private_constant_indexing
120
- index(<<~RUBY)
121
- class A
122
- B = 1
123
- private_constant(:B)
124
-
125
- C = 2
126
- private_constant("C")
127
-
128
- D = 1
129
- end
130
- RUBY
131
-
132
- b_const = @index["A::B"]&.first #: as !nil
133
- assert_predicate(b_const, :private?)
134
-
135
- c_const = @index["A::C"]&.first #: as !nil
136
- assert_predicate(c_const, :private?)
137
-
138
- d_const = @index["A::D"]&.first #: as !nil
139
- assert_predicate(d_const, :public?)
140
- end
141
-
142
- def test_marking_constants_as_private_reopening_namespaces
143
- index(<<~RUBY)
144
- module A
145
- module B
146
- CONST_A = 1
147
- private_constant(:CONST_A)
148
-
149
- CONST_B = 2
150
- CONST_C = 3
151
- end
152
-
153
- module B
154
- private_constant(:CONST_B)
155
- end
156
- end
157
-
158
- module A
159
- module B
160
- private_constant(:CONST_C)
161
- end
162
- end
163
- RUBY
164
-
165
- a_const = @index["A::B::CONST_A"]&.first #: as !nil
166
- assert_predicate(a_const, :private?)
167
-
168
- b_const = @index["A::B::CONST_B"]&.first #: as !nil
169
- assert_predicate(b_const, :private?)
170
-
171
- c_const = @index["A::B::CONST_C"]&.first #: as !nil
172
- assert_predicate(c_const, :private?)
173
- end
174
-
175
- def test_marking_constants_as_private_with_receiver
176
- index(<<~RUBY)
177
- module A
178
- module B
179
- CONST_A = 1
180
- CONST_B = 2
181
- end
182
-
183
- B.private_constant(:CONST_A)
184
- end
185
-
186
- A::B.private_constant(:CONST_B)
187
- RUBY
188
-
189
- a_const = @index["A::B::CONST_A"]&.first #: as !nil
190
- assert_predicate(a_const, :private?)
191
-
192
- b_const = @index["A::B::CONST_B"]&.first #: as !nil
193
- assert_predicate(b_const, :private?)
194
- end
195
-
196
- def test_indexing_constant_aliases
197
- index(<<~RUBY)
198
- module A
199
- module B
200
- module C
201
- end
202
- end
203
-
204
- FIRST = B::C
205
- end
206
-
207
- SECOND = A::FIRST
208
- RUBY
209
-
210
- unresolve_entry = @index["A::FIRST"]&.first #: as Entry::UnresolvedConstantAlias
211
- assert_instance_of(Entry::UnresolvedConstantAlias, unresolve_entry)
212
- assert_equal(["A"], unresolve_entry.nesting)
213
- assert_equal("B::C", unresolve_entry.target)
214
-
215
- resolved_entry = @index.resolve("A::FIRST", [])&.first #: as Entry::ConstantAlias
216
- assert_instance_of(Entry::ConstantAlias, resolved_entry)
217
- assert_equal("A::B::C", resolved_entry.target)
218
- end
219
-
220
- def test_aliasing_namespaces
221
- index(<<~RUBY)
222
- module A
223
- module B
224
- module C
225
- end
226
- end
227
-
228
- ALIAS = B
229
- end
230
-
231
- module Other
232
- ONE_MORE = A::ALIAS
233
- end
234
- RUBY
235
-
236
- unresolve_entry = @index["A::ALIAS"]&.first #: as Entry::UnresolvedConstantAlias
237
- assert_instance_of(Entry::UnresolvedConstantAlias, unresolve_entry)
238
- assert_equal(["A"], unresolve_entry.nesting)
239
- assert_equal("B", unresolve_entry.target)
240
-
241
- resolved_entry = @index.resolve("ALIAS", ["A"])&.first #: as Entry::ConstantAlias
242
- assert_instance_of(Entry::ConstantAlias, resolved_entry)
243
- assert_equal("A::B", resolved_entry.target)
244
-
245
- resolved_entry = @index.resolve("ALIAS::C", ["A"])&.first #: as Entry::Module
246
- assert_instance_of(Entry::Module, resolved_entry)
247
- assert_equal("A::B::C", resolved_entry.name)
248
-
249
- unresolve_entry = @index["Other::ONE_MORE"]&.first #: as Entry::UnresolvedConstantAlias
250
- assert_instance_of(Entry::UnresolvedConstantAlias, unresolve_entry)
251
- assert_equal(["Other"], unresolve_entry.nesting)
252
- assert_equal("A::ALIAS", unresolve_entry.target)
253
-
254
- resolved_entry = @index.resolve("Other::ONE_MORE::C", [])&.first
255
- assert_instance_of(Entry::Module, resolved_entry)
256
- end
257
-
258
- def test_indexing_same_line_constant_aliases
259
- index(<<~RUBY)
260
- module A
261
- B = C = 1
262
- D = E ||= 1
263
- F = G::H &&= 1
264
- I::J = K::L = M = 1
265
- end
266
- RUBY
267
-
268
- # B and C
269
- unresolve_entry = @index["A::B"]&.first #: as Entry::UnresolvedConstantAlias
270
- assert_instance_of(Entry::UnresolvedConstantAlias, unresolve_entry)
271
- assert_equal(["A"], unresolve_entry.nesting)
272
- assert_equal("C", unresolve_entry.target)
273
-
274
- resolved_entry = @index.resolve("A::B", [])&.first #: as Entry::ConstantAlias
275
- assert_instance_of(Entry::ConstantAlias, resolved_entry)
276
- assert_equal("A::C", resolved_entry.target)
277
-
278
- constant = @index["A::C"]&.first #: as Entry::Constant
279
- assert_instance_of(Entry::Constant, constant)
280
-
281
- # D and E
282
- unresolve_entry = @index["A::D"]&.first #: as Entry::UnresolvedConstantAlias
283
- assert_instance_of(Entry::UnresolvedConstantAlias, unresolve_entry)
284
- assert_equal(["A"], unresolve_entry.nesting)
285
- assert_equal("E", unresolve_entry.target)
286
-
287
- resolved_entry = @index.resolve("A::D", [])&.first #: as Entry::ConstantAlias
288
- assert_instance_of(Entry::ConstantAlias, resolved_entry)
289
- assert_equal("A::E", resolved_entry.target)
290
-
291
- # F and G::H
292
- unresolve_entry = @index["A::F"]&.first #: as Entry::UnresolvedConstantAlias
293
- assert_instance_of(Entry::UnresolvedConstantAlias, unresolve_entry)
294
- assert_equal(["A"], unresolve_entry.nesting)
295
- assert_equal("G::H", unresolve_entry.target)
296
-
297
- resolved_entry = @index.resolve("A::F", [])&.first #: as Entry::ConstantAlias
298
- assert_instance_of(Entry::ConstantAlias, resolved_entry)
299
- assert_equal("A::G::H", resolved_entry.target)
300
-
301
- # I::J, K::L and M
302
- unresolve_entry = @index["A::I::J"]&.first #: as Entry::UnresolvedConstantAlias
303
- assert_instance_of(Entry::UnresolvedConstantAlias, unresolve_entry)
304
- assert_equal(["A"], unresolve_entry.nesting)
305
- assert_equal("K::L", unresolve_entry.target)
306
-
307
- resolved_entry = @index.resolve("A::I::J", [])&.first #: as Entry::ConstantAlias
308
- assert_instance_of(Entry::ConstantAlias, resolved_entry)
309
- assert_equal("A::K::L", resolved_entry.target)
310
-
311
- # When we are resolving A::I::J, we invoke `resolve("K::L", ["A"])`, which recursively resolves A::K::L too.
312
- # Therefore, both A::I::J and A::K::L point to A::M by the end of the previous resolve invocation
313
- resolved_entry = @index["A::K::L"]&.first #: as Entry::ConstantAlias
314
- assert_instance_of(Entry::ConstantAlias, resolved_entry)
315
- assert_equal("A::M", resolved_entry.target)
316
-
317
- constant = @index["A::M"]&.first
318
- assert_instance_of(Entry::Constant, constant)
319
- end
320
-
321
- def test_indexing_or_and_operator_nodes
322
- index(<<~RUBY)
323
- A ||= 1
324
- B &&= 2
325
- C &= 3
326
- D::E ||= 4
327
- F::G &&= 5
328
- H::I &= 6
329
- RUBY
330
-
331
- assert_entry("A", Entry::Constant, "/fake/path/foo.rb:0-0:0-7")
332
- assert_entry("B", Entry::Constant, "/fake/path/foo.rb:1-0:1-7")
333
- assert_entry("C", Entry::Constant, "/fake/path/foo.rb:2-0:2-6")
334
- assert_entry("D::E", Entry::Constant, "/fake/path/foo.rb:3-0:3-10")
335
- assert_entry("F::G", Entry::Constant, "/fake/path/foo.rb:4-0:4-10")
336
- assert_entry("H::I", Entry::Constant, "/fake/path/foo.rb:5-0:5-9")
337
- end
338
-
339
- def test_indexing_constant_targets
340
- index(<<~RUBY)
341
- module A
342
- B, C = [1, Y]
343
- D::E, F::G = [Z, 4]
344
- H, I::J = [5, B]
345
- K, L = C
346
- end
347
-
348
- module Real
349
- Z = 1
350
- Y = 2
351
- end
352
- RUBY
353
-
354
- assert_entry("A::B", Entry::Constant, "/fake/path/foo.rb:1-2:1-3")
355
- assert_entry("A::C", Entry::UnresolvedConstantAlias, "/fake/path/foo.rb:1-5:1-6")
356
- assert_entry("A::D::E", Entry::UnresolvedConstantAlias, "/fake/path/foo.rb:2-2:2-6")
357
- assert_entry("A::F::G", Entry::Constant, "/fake/path/foo.rb:2-8:2-12")
358
- assert_entry("A::H", Entry::Constant, "/fake/path/foo.rb:3-2:3-3")
359
- assert_entry("A::I::J", Entry::UnresolvedConstantAlias, "/fake/path/foo.rb:3-5:3-9")
360
- assert_entry("A::K", Entry::Constant, "/fake/path/foo.rb:4-2:4-3")
361
- assert_entry("A::L", Entry::Constant, "/fake/path/foo.rb:4-5:4-6")
362
- end
363
-
364
- def test_indexing_constant_targets_with_splats
365
- index(<<~RUBY)
366
- A, *, B = baz
367
- C, = bar
368
- (D, E) = baz
369
- F, G = *baz, qux
370
- H, I = [baz, *qux]
371
- J, L = [*something, String]
372
- M = [String]
373
- RUBY
374
-
375
- assert_entry("A", Entry::Constant, "/fake/path/foo.rb:0-0:0-1")
376
- assert_entry("B", Entry::Constant, "/fake/path/foo.rb:0-6:0-7")
377
- assert_entry("D", Entry::Constant, "/fake/path/foo.rb:2-1:2-2")
378
- assert_entry("E", Entry::Constant, "/fake/path/foo.rb:2-4:2-5")
379
- assert_entry("F", Entry::Constant, "/fake/path/foo.rb:3-0:3-1")
380
- assert_entry("G", Entry::Constant, "/fake/path/foo.rb:3-3:3-4")
381
- assert_entry("H", Entry::Constant, "/fake/path/foo.rb:4-0:4-1")
382
- assert_entry("I", Entry::Constant, "/fake/path/foo.rb:4-3:4-4")
383
- assert_entry("J", Entry::Constant, "/fake/path/foo.rb:5-0:5-1")
384
- assert_entry("L", Entry::Constant, "/fake/path/foo.rb:5-3:5-4")
385
- assert_entry("M", Entry::Constant, "/fake/path/foo.rb:6-0:6-12")
386
- end
387
-
388
- def test_indexing_destructuring_an_array
389
- index(<<~RUBY)
390
- Baz = [1, 2]
391
- Foo, Bar = Baz
392
- This, That = foo, bar
393
- RUBY
394
-
395
- assert_entry("Baz", Entry::Constant, "/fake/path/foo.rb:0-0:0-12")
396
- assert_entry("Foo", Entry::Constant, "/fake/path/foo.rb:1-0:1-3")
397
- assert_entry("Bar", Entry::Constant, "/fake/path/foo.rb:1-5:1-8")
398
- assert_entry("This", Entry::Constant, "/fake/path/foo.rb:2-0:2-4")
399
- assert_entry("That", Entry::Constant, "/fake/path/foo.rb:2-6:2-10")
400
- end
401
- end
402
- end